Comments 47
раз, два, три
То-ли ссылки не вставились, то ли ещё что. А какие есть, а то я кроме django-any и его форка больше ничего не знаю?
поправили ссылки, спасибо. Я знаю хорошие отзывы про django-dynamic-fixture :)
Есть ещё factory_boy и как по мне, с ним удобнее
Еще по теме TDD с django тут несколько уроков.
Перед каждым запуском теста база не создается. Она создается один раз, потом перед каждым тестом говорится start transaction, а после tearDown() говорится rollback;
> Для ускорения тестовой базы можно еще поставить в postgresql.conf:
> Прирост тоже ощущается. Ну и SSD винчестеры тоже хорошо :).
Просто инициализируйте тестовый PG-кластер в /dev/shm
> Прирост тоже ощущается. Ну и SSD винчестеры тоже хорошо :).
Просто инициализируйте тестовый PG-кластер в /dev/shm
Кстати,
>Такие тесты проще включить в процесс сборки, они достаточно быстро проходят (3-4 минуты ~250 тестов) и не задерживают особо релиз, они рядом с кодом. За временем выполнения тестов нужно следить и принимать меры по ускорению, т.к. количество тестов будет только расти, а значит — и время их выполнения.
Вполне логично в таких случаях сразу ориентироваться на распределённое тестирование. Для py.test существуют простые плагины, которые реализуют такую возможность. Для nose довольно легко написать похожий плагин, взяв за основу pytest-xdist.
>Такие тесты проще включить в процесс сборки, они достаточно быстро проходят (3-4 минуты ~250 тестов) и не задерживают особо релиз, они рядом с кодом. За временем выполнения тестов нужно следить и принимать меры по ускорению, т.к. количество тестов будет только расти, а значит — и время их выполнения.
Вполне логично в таких случаях сразу ориентироваться на распределённое тестирование. Для py.test существуют простые плагины, которые реализуют такую возможность. Для nose довольно легко написать похожий плагин, взяв за основу pytest-xdist.
По изоляции мне нравятся больше интеграционные тесты, по тестируемому объекту — функциональные. У таких тестов очень большое покрытие кода, это и плюс и минус одновременно… они достаточно быстро проходят (3-4 минуты ~250 тестов)как будто про нас. :) тоже с этого начинали. и щастье при первом рефакторинге. и разочарование, когда более-менее освоили метод, а количество тестов перевалило за сотню — запуск занимает какое-то неразумное время, при этом видно невооруженным глазом, что получаемая польза не оправдывает вложения.
чем крупнее кусок системы, охватываемый тестом, тем больше у него параметров состояния и тем меньше шансов проверить, пускай даже лишь существенные, их комбинации, ничего не упустив. при этом, чем больше глубина куска (по задействованным уровням системы), тем менее очевидны связи между этими параметрами, с точки зрения внешнего наблюдателя, коим является тест.
мне кажется, что «большое покрытие кода» интеграционными тестами — иллюзия. как раз о коде они дают лишь крайне поверхностное, оценочное представление. по сто раз дергают одни и те же куски, пропуская значимые граничные аспекты. отсюда эффективность. данный вид тестов хоть и хорош в начале, но в качестве основного средства tdd-разработки не особо практичен. вроде как хождение на четвереньках.
Это вопрос о гранулярности тестов. Потому что
> чем крупнее кусок системы, охватываемый тестом, тем больше у него параметров состояния
>по сто раз дергают одни и те же куски
— это те самые симптомы, о которых начинают упоминать в случаях неправильной гранулярности.
> чем крупнее кусок системы, охватываемый тестом, тем больше у него параметров состояния
>по сто раз дергают одни и те же куски
— это те самые симптомы, о которых начинают упоминать в случаях неправильной гранулярности.
у меня опыт интенсивного TDD в python уже пару лет точно — это осознанный выбор, с учетом опыта…
Да покрытие кода не говорит про качество тестов, но я описал плюс покрытия кода для питона.
Нужно писать хорошие тесты, как и нужно писать хороший код :).
Если поверх WSGI трудно тестировать какую-то логику, нужно спускаться ниже, и ниже уже проверять тонкую логику (например: на джанго форме или моделе) — это уже ближе к юнит тестам…
Тест поверх WSGI все равно нужен — он проверит код в реальном воркфлоу :), пусть даже не со всей логикой.
Да покрытие кода не говорит про качество тестов, но я описал плюс покрытия кода для питона.
Нужно писать хорошие тесты, как и нужно писать хороший код :).
Если поверх WSGI трудно тестировать какую-то логику, нужно спускаться ниже, и ниже уже проверять тонкую логику (например: на джанго форме или моделе) — это уже ближе к юнит тестам…
Тест поверх WSGI все равно нужен — он проверит код в реальном воркфлоу :), пусть даже не со всей логикой.
на случай, если кто будет тестить
без fsync = off база создаетс адски долго. А с ним — реально секунды
без fsync = off база создаетс адски долго. А с ним — реально секунды
Я так понял- автор выставил код уже с привязкой к совему проекту, а не реюзабельное решение
в приципе там особо привязок нет, я немного обновил gist, добавил requirements.txt и пару коментов. У нас это пакет, поэтому нужно его создать… Но для публикации идеи мне казалось gist-a достаточно…
psql(
'create extension cube;'
'create extension earthdistance;'
)
Про редис в статье ни слова
def mock_http(self):
self.mock_func('urllib2.urlopen')
self.mock_func('urllib2.build_opener')
self.mock_func('requests.api.request')
Вот это зачем?
1.
2. да про редис забыл :), для зачистки обвертка…
3.
ок, согласен gist заточен под проект :)
setup_databases
пишем под себя, написал об этом в шапке раннера2. да про редис забыл :), для зачистки обвертка…
3.
mock_http
— тесты не должны сутчатся на внешний http, т.к. он может отвалиться или сети вообще не быть, а тесты должны ходить в не зависимости, отвечает сайт или нет. Поэтому мы мокаем http запросы. mock_http
нужен, чтоб видеть что тест делает http и свалиться, в трейсбеке можно увидеть, где возник этот запрос — потом идем мокаем :)… так же можно запустить с ключем --without-mock-http
:)ок, согласен gist заточен под проект :)
Просто у меня в голове крутилась именно идея того, что в репе лежит sql ый дамп постгри и его используют вместо фикстур.
И в текстах он указывается также, как и фикстуры. Так можно даже организовывать поддержку транимых процедур или тригеров.
И в текстах он указывается также, как и фикстуры. Так можно даже организовывать поддержку транимых процедур или тригеров.
sql — дамп нужно также поддерживать, как и статические фикстуры, что тут другого?
В
Потом между тестами мы ее будем создавать с
В
setup_databases
(это из gist) можно все что угодно сделать с базой, в том числе и подтянуть sql дамп с диска, или прям строкой записать в базу тригер — это не важно.Потом между тестами мы ее будем создавать с
WITH TEMPLATE
(мы ведь про postgres) и там у нас будут уже все тригиры и данные, которые мы туда запихнем на шаге создания бд… Эта операция (создание бд с WITH TEMPLATE
) быстрее чем flush
на большой базе, но медленее транзакций. Про это в статье говориться.Выигрыш будет не только между тестами но и в первом тесте. А при TDD это реально выигрыш во времени. Нет?
Не вижу сложностей в поддержке sql дампа в репе. Саус накатывает миграции. Все инсерты идут один за другим в отиличии от фикстур, поэтому легко резолвить конфликты в дампах. Помоему сказка.
Не вижу сложностей в поддержке sql дампа в репе. Саус накатывает миграции. Все инсерты идут один за другим в отиличии от фикстур, поэтому легко резолвить конфликты в дампах. Помоему сказка.
у нас есть отдельно данные для теста, там дамп мама не горюй :)
— при кажой миграции схемы, нужно переливать дамп
— одновременное редактирование схемы — что тогда, делать мердж будет напряжно?
у нас большая достаточно команда, гит и куча бранчей, тестовая база — дамп на 5 гиг :)… Все не так-то просто :)
— при кажой миграции схемы, нужно переливать дамп
— одновременное редактирование схемы — что тогда, делать мердж будет напряжно?
у нас большая достаточно команда, гит и куча бранчей, тестовая база — дамп на 5 гиг :)… Все не так-то просто :)
5ти гиговая база для тестов? Мы же сейчас не про стресс тестирование говорим?
А как вы ее поддерживаете? По сути тоже самое, только без дампа. Под каждый бранч отдельная 5ти гиговая дура висит :)
А как вы ее поддерживаете? По сути тоже самое, только без дампа. Под каждый бранч отдельная 5ти гиговая дура висит :)
а без django_nose можно это реализовать наследником от обыкновенного DjangoTestSuiteRunner?
А в каких случаях вы используете флаг _test_unique_db а в каких нет?
У нас был момент, когда мы использовали только уникальную базу, а когда подключали транзакции, то часть тестов не работали в транзакции и почему было не очевидно :)… Поэтому те которые не работали оставили с уникальной базой. В общем пока точно не знаю, предстоит разобраться… :)
а свойство _test_db — нужно на случай использования различных Баз?
а можешь про вот это объяснить по подробнее?
* изолированность от внешнего мира (внешние http запросы должны мокаться);
Я не очень понял.
* изолированность от внешнего мира (внешние http запросы должны мокаться);
Я не очень понял.
тут 3 пункт habrahabr.ru/company/ostrovok/blog/146552/#comment_4936729, вроде ответил :)
у нас много внешних зависимостей: шлюзы оплаты, провайдеры, просто какие-то внешние сервисы с апи… это все нужно мокать — мы мокаем… И для этого обвертка
у нас много внешних зависимостей: шлюзы оплаты, провайдеры, просто какие-то внешние сервисы с апи… это все нужно мокать — мы мокаем… И для этого обвертка
mock_http
, чтоб разработчики понимали, что тест стучится во внешний мир…gist.github.com/3017754 небольшая вариация на тему :)
За основу — взял Ваш. Правда убрал пару, как мне показалось, не нужных вещей.
Можете глянуть? Что я могу упустить?
За основу — взял Ваш. Правда убрал пару, как мне показалось, не нужных вещей.
Можете глянуть? Что я могу упустить?
сразу что в глаза бросается, это если у нескольких людей одинаковый TEST_DB_PREFIX
TEST_DB_PREFIX = settings.DATABASES['default']['NAME'] + '__'
то так нельзя запустить тесты нескольким пользователям с базой на одном серваке… т.к. все базы у первого попытаются грохнуть Runner второго…
Ну и зря убрали REUSE_DB, я про это в статье писал, запуск одного отдельного теста должен быть 1-2 секунды, а не даже 10-20сек, а создание базы может занять и больше времени…
TEST_DB_PREFIX = settings.DATABASES['default']['NAME'] + '__'
то так нельзя запустить тесты нескольким пользователям с базой на одном серваке… т.к. все базы у первого попытаются грохнуть Runner второго…
Ну и зря убрали REUSE_DB, я про это в статье писал, запуск одного отдельного теста должен быть 1-2 секунды, а не даже 10-20сек, а создание базы может занять и больше времени…
Если тип БД не критичен, то при разработке для тестов можно использовать sqlite3 и в качестве имени БД ':memory:' — тесты выполняются на порядок быстрее.
Один из признаков псевдо-TDD — необходимость «поддерживать тесты, чтобы не стали мертвым грузом»:
В TDD тесты правятся первыми не потому, что их обязательно надо поддерживать, а потому, что они определяют требования/спецификации: изменились бизнес-требования (или другой код) -> изменить формальные спецификации (а это и есть тесты) -> изменить сам код так, чтобы он удовлетворял новым спецификациям.
Ключевая разница между написанием любых автоматизированных тестов и именно TDD — в голове: тесты воспринимаются не как груз для проверки кода, который еще почему-то нужно писать перед самим кодом, а как естественный этап проектирования: от спецификаций на естественном языке переходим к спецификациям в программном коде (вместо или в дополнение к рисованию на бумажке), которые и помогают написать правильный код.
В TDD тесты правятся первыми не потому, что их обязательно надо поддерживать, а потому, что они определяют требования/спецификации: изменились бизнес-требования (или другой код) -> изменить формальные спецификации (а это и есть тесты) -> изменить сам код так, чтобы он удовлетворял новым спецификациям.
Ключевая разница между написанием любых автоматизированных тестов и именно TDD — в голове: тесты воспринимаются не как груз для проверки кода, который еще почему-то нужно писать перед самим кодом, а как естественный этап проектирования: от спецификаций на естественном языке переходим к спецификациям в программном коде (вместо или в дополнение к рисованию на бумажке), которые и помогают написать правильный код.
А вы пробовали смонтировать ramdisk и положить туда БД? Пример для мускула github.com/miracle2k/linuxutils/blob/master/mysqld-ram.sh
«найти сломанное место иногда трудно»
Не согласен, использую TDD около 3ёх лет и за редким исключением проблемы находятся мгновенно.
Не согласен, использую TDD около 3ёх лет и за редким исключением проблемы находятся мгновенно.
в функциональных тестах с большим покрытием кода? в каждом куске кода, который такой тест покрывает потенциально может быть ошибка, если код знаешь с нуля, то да все найдется быстро, если в проект пришел через код его существования, то все тонкости не будешь знать…
с юнит тестами да все просто — но на то они и юнит…
с юнит тестами да все просто — но на то они и юнит…
Sign up to leave a comment.
Внедряем TDD с django и postgres