Показаны сообщения с ярлыком nosetests. Показать все сообщения
Показаны сообщения с ярлыком nosetests. Показать все сообщения

2 мая 2012 г.

Окончательно дружим Flask и nosetests

Не секрет, что Flask и так хорошо дружит с nosetests, но до сегодняшнего дня был один очень раздражющий момент в их взаимоотношениях :)

Как мы все знаем nosetests по дефолту захватывает все из stdout/stderr и логгинга, чтоб при запуске тестов вывод не засорялся ненужной нам информацией. Однако в дебаг-моде Flask кладет на всех и устанавливает с помощью flask.logging.create_logger функции хэндлер, который начинает срать в консоль при каждом удобном случае, причем минуя все ранее установленные хэндлеры. Итог: куча ненужной логгинг информации при запуске тестов как:

(env)$ TESTING=1 nosetets -c -v -w <package>

Не хорошо, но In mock we trust, так что все что надо - это замокать упомянутую выше функцию в случае, когда мы запускаем тесты в дебаг-моде:

if TESTING and DEBUG:
    from flask import logging as flask_logging

    def mock_create_logger(app):
        return logging.getLogger(app.logger_name)

    flask_logging.create_logger = mock_create_logger

Помещаем этот сниппет в settings.py, затем не забываем загрузить настройки как import settings; app.config.from_object(settings) в нашем app.py - и получаем счастье, nosetests уверенно захватывает все нужное и вывод тестов чист и аккуратен.

Полный гист доступен на Гитхабе, если кто-то готов предложить более красивый вариант решения проблемы - жду в комментариях.

27 января 2012 г.

Пару заметок о coverage, nosetests и lettuce

Думаю ни для кого не секрет, что в nosetests уже есть встроенная поддержка coverage, однако там нет очень важной фичи coverage, а именно возможности дополнять файл данных после каждого следующего запуска тестов (опция -a --append в coverage run).

Зачем это может понадобится? Самый простой пример: если в проекте есть и юнит тесты, и интеграционные, и не дай бог тесты, работающие с реальными данными :) Т.е. если мы запускаем все тесты перед деплоем не просто nosetests ..., а связкой из nosetests ... && nosetests ... && nosetests ..., в таком случае добавление --with-coverage в каждую итерацию nosetests даст нам три совсем ненужных таблицы покрытия, где каждая таблица будет отличаться от предыдущей и смерджить их воедино не выйдет - а это совсем не то, что нам надо.

Что делать? На самом деле ничего сложного, просто меняем:

$ nosetests --with-coverage ... && \
  nosetests --with-coverage ... && \
  nosetests --with-coverage ...

на:

$ coverage run `which nosetests` ... && \
  coverage run -a `which nosetests` ... && \
  coverage run -a `which nosetests` ... && \
  coverage report -m

В итоге получим то, чего добивались, а именно таблицу покрытия кода всеми тестами.

И да, раз уже заговорили про coverage, вы не забываете про использование .coveragerc? Очень полезная вещь!

Так что теперь, если в проекте используются и lettuce, и nosetests - посчитать покрытие кода не составит особого труда, используя coverage run `which lettuce` ... && coverage run -a `which nosetests` ...

И последнее на сегодня, при запуске lettuce тестов, не забывайте указывать путь не к директории, в которой есть features, а к самой директории features. Я на этом моменте очень сильно злился!