не отработает в данной ситуации как нужно и не найдет Сашу, поскольку LIKE не умеет парсить списки, извлекать значения и трактовать их как аргументы для сравнения с шаблоном. ’Ваня, Саша’ в данном случае неатомарное значение типа список строк. Чтобы научить SQL работать с такими данными, нужно либо расширить язык, либо упростить модель до 1NF. Декомпозиция до 1NF достигается разбиением составного значения на атомарные
Кажется здесь критерием отбора служит часть слова — буква. Не значит-ли это, что атомарными значениями в данном являются буквы алфавита, а не имена?
Или по другому задам вопрос: как, с точки зрения 1NF, понимать «атомарность»?
Правильно понимаю, что «детали» такого контракта нужно прописывать возле каждого метода, где упоминаются часы — принимаются аргументами или возвращаются в результате? Если так, то тип кажется выгоднее — здесь реализация будет инкапсулирована внутри единтсвенного класса.
@Ensures({
"result >= 0",
"result <= 23"
})
int getHour();
Кажется, проблема этого кода в том, что getHour() возрващает абстактный int, вместо собственно «часов». Если завести специальный тип Hour (у нас ведь ООП в конце-концов), то вся эта атрибутика будет не особенно нужна:
Тесты — суть выражение функциональных спецификаций. Если в тесте не отражены (явно или же очевидным образом) какие-то условия, считайте что на них нет постановки. В самом деле, постановка может быть не полной. Но в этом виновата лишь ваша лень — при чем тут TDD? :) Кстати, тут могут быть полезны вот такие феньки, которые выводят лейаут теста на «человеческом» языке — обратно, в виде спецификации.
Если вы делаете одно простое изменение в коде, и вам нужно перелопатить десяток тестов, это означает что вы поменяли шаги местами. сначала меняется один тест — затем вносится изменение в код.
В процессе выполнения теста создаются идеальные условия для дебага.
Если одно и то же изменение в коде вызывает каскадное изменение других тестов, это является сигналом о сильной связанности — т.е. ваша система тестов попросту плохо спроектирована. (сюрприз, чтобы тесты было легко поддерживать, их тоже необходимо вдумчиво проектировать — так же тщательно как и любой другой код. поэтому как раз-таки для «быдлокодеров» от ни нет ни какой пользы).
В принципе, я согласен. Но есть вырожденные ситуации, где, как мне кажется, это может быть полезно.
Например, если ваше приложение и есть инсталлятор — где инициализация virtualenv лишь первый шаг, а дальше накладываются пачти, создаются конфиги и т.п.
Я использую такую возможность в скрипте, запускающем тесты для проекта. Это создает единую точку входа, упрощая интеграцию с CI-сервером. А «интегрированный» деплоймент позволяет лишний раз убедиться, что все зависимости прописаны.
У pip есть замечательная фича — он умеет создавать бандлы (bundle) для установки всех зависимостей «оффлайн». Единственная проблема — для распаковки бандла на целевом хосте должен быть установлен сам pip, желательно не самый старый. Путем такого трюка с virtualenv это ограничение достаточно легко обходится.
согласен. в принципе, тем хуже для примера. здесь я хотел показать, что virtualenv'у, устанавливаемому таким способом, можно передавать знакомые параметры.
ага, это поиск. вы сами выбираете скорость, с которой хотите приближаться к цели. будете идти мелкими шагами — выйграете в контроле, но проиграете в темпе. крупными шагами — наоборот — пойдете быстро, но можете «не вписаться в поворот» и пролететь мимо. со временем найдете оптимальный.
все известные мне тест-фреймоврки содержат асерты для сравнения значений с учетом типа. PhpUnit::assertSame(), например. либо напишите в асерте count() === 10 — если вернет не число, тоже увидите fail.
ps: для неформализованных требований вы вряд-ли сможете написать тест ;)
Вот только на этом компьютере у Васи, а на остальных двух сотнях работает. У него там, правда, кондёры на материнке полететели, но программа ведь все-равно должна работать, правда?
что «правда»? требовние работать на уникальном компрьютере Васи с полетевшими кондерами было с самого начала? если да, то вы этот кейс должны были уже вусмерть затеститровать. а если же нет — это либо нарушение технических требований (оборудование должно быть исправно), либо новая фича, за отдельные деньги. при чем тут tdd? тесты — это не только юнит тесты.
Я пришел к автоматическим тестам очень просто — проанализировав беклог только что закончившейся очень нервной итерации. Проекту — год. Оказалось, что лишь 20% сделанных задач было новыми штуками, которые двигают нас вперед, а 80% задач стало разлинчного рода багофиксингом. Причем в конце итерации, котрый мы «отыгрывали» уже в дополнительное время, было такое ощущение, что всё вышло из под контроля и идет «в разнос» — когда каждая доделка приводит к появлению/выявлению еще пары новых багов — и только каким-то чудом оно в итоге «сошлось».
юнти-тесты это модульное тестирование — для маленьких атомарных единиц функционала. ну не бывает таких здоровых модулей, чтобы сразу и gui и база данных. ;)
нужен метод, возвращающий объект класса MyClass с одним свойством и конструктором с параметром — значением этого свойства.
…
Устал :) В общем ещё с десяток итераций и получим код
— как сделать шаг? — нужно поднять ногу и, сохраняя равновесие, перенести её на 1 милиметр вперед, затем еще на 1 миллиметр, потом еще на 1 миллиметр,… — фу, как сложно ходить! ;)
тест — это та же запись требований, только на языке программирования. у вас тут одно понятное предложение. описывайте в тесте, сразу (и только) то, что требуется. зачем вся эта чехорда?
По-моему это обычное дело, когда заказчик выдвигает абстрактные требования. У него есть какая-то проблема, он не знает как её решить (скажем, потому что не обладает нужными компетенциями), но очень хочет и для этого обращается к разработчику.
Естественно, что заказчик описывает проблему абстрактно: в меру собственного понимания, каких-то ощущений и эмоций. Задача разработчика как раз и состоит в том, чтобы выявить «паталогию», придумать решение и реализовать.
Когда разработчик, не разобравшись в проблеме и не придумав решение, бросается «кодить» — это клиника — такую ситуацию, думаю, можно не рассматривать.
Если ваш заказчик берет на себя функцию принятия технических решений (например, размер шрифта), это скорее всего означает, что в ваших отношениях с ним что-то не так. И вам нужно, в первую очередь, решить этот вопрос. Ведь заказчик менее компетентен в сфере разрботки, нежели вы, и его действия вполне ожидаемо будут неверными. (в таком случае, он тупо будет учиться, на собтсвенных ошибках, — которые скорее всего будут выдаваться за ваши).
Может быть он вам не доверяет? В этом случае постарайтесь доказать свою компетенцию, чтобы у него не было сомнений. А может быть вы сами снимаете с себя ответственность за выработку решений? Тогда естественно эту функцию он будет брать на себя и станет выдумывать решение сам (ведь больше не кому).
Кажется здесь критерием отбора служит часть слова — буква. Не значит-ли это, что атомарными значениями в данном являются буквы алфавита, а не имена?
Или по другому задам вопрос: как, с точки зрения 1NF, понимать «атомарность»?
Кажется, проблема этого кода в том, что getHour() возрващает абстактный int, вместо собственно «часов». Если завести специальный тип Hour (у нас ведь ООП в конце-концов), то вся эта атрибутика будет не особенно нужна:
В чем смысл?
Если вы делаете одно простое изменение в коде, и вам нужно перелопатить десяток тестов, это означает что вы поменяли шаги местами. сначала меняется один тест — затем вносится изменение в код.
В процессе выполнения теста создаются идеальные условия для дебага.
Если одно и то же изменение в коде вызывает каскадное изменение других тестов, это является сигналом о сильной связанности — т.е. ваша система тестов попросту плохо спроектирована. (сюрприз, чтобы тесты было легко поддерживать, их тоже необходимо вдумчиво проектировать — так же тщательно как и любой другой код. поэтому как раз-таки для «быдлокодеров» от ни нет ни какой пользы).
Например, если ваше приложение и есть инсталлятор — где инициализация virtualenv лишь первый шаг, а дальше накладываются пачти, создаются конфиги и т.п.
Я использую такую возможность в скрипте, запускающем тесты для проекта. Это создает единую точку входа, упрощая интеграцию с CI-сервером. А «интегрированный» деплоймент позволяет лишний раз убедиться, что все зависимости прописаны.
У pip есть замечательная фича — он умеет создавать бандлы (bundle) для установки всех зависимостей «оффлайн». Единственная проблема — для распаковки бандла на целевом хосте должен быть установлен сам pip, желательно не самый старый. Путем такого трюка с virtualenv это ограничение достаточно легко обходится.
Если нужные зависимости прописать в файл requirements.pip, например:
и добавить в начало запускающего модуля вашего проекта вот такой код:
тогда все необходимое установится автоматически при первом запуске скрипта, и сразу же станет доступным к использованию.
ps: для неформализованных требований вы вряд-ли сможете написать тест ;)
что «правда»? требовние работать на уникальном компрьютере Васи с полетевшими кондерами было с самого начала? если да, то вы этот кейс должны были уже вусмерть затеститровать. а если же нет — это либо нарушение технических требований (оборудование должно быть исправно), либо новая фича, за отдельные деньги. при чем тут tdd? тесты — это не только юнит тесты.
— как сделать шаг? — нужно поднять ногу и, сохраняя равновесие, перенести её на 1 милиметр вперед, затем еще на 1 миллиметр, потом еще на 1 миллиметр,… — фу, как сложно ходить! ;)
тест — это та же запись требований, только на языке программирования. у вас тут одно понятное предложение. описывайте в тесте, сразу (и только) то, что требуется. зачем вся эта чехорда?
Естественно, что заказчик описывает проблему абстрактно: в меру собственного понимания, каких-то ощущений и эмоций. Задача разработчика как раз и состоит в том, чтобы выявить «паталогию», придумать решение и реализовать.
Когда разработчик, не разобравшись в проблеме и не придумав решение, бросается «кодить» — это клиника — такую ситуацию, думаю, можно не рассматривать.
Если ваш заказчик берет на себя функцию принятия технических решений (например, размер шрифта), это скорее всего означает, что в ваших отношениях с ним что-то не так. И вам нужно, в первую очередь, решить этот вопрос. Ведь заказчик менее компетентен в сфере разрботки, нежели вы, и его действия вполне ожидаемо будут неверными. (в таком случае, он тупо будет учиться, на собтсвенных ошибках, — которые скорее всего будут выдаваться за ваши).
Может быть он вам не доверяет? В этом случае постарайтесь доказать свою компетенцию, чтобы у него не было сомнений. А может быть вы сами снимаете с себя ответственность за выработку решений? Тогда естественно эту функцию он будет брать на себя и станет выдумывать решение сам (ведь больше не кому).