Питоничность в тестировании

Игорь Стариков / idle sign

Видео выступления

Автор

  • Несу Python в массы:
    • Рассказываю о нём
    • Поддерживаю сайт — pythonz.net
    • Перевожу и озвучиваю доклады с англоязычных PyCon
  • Пишу код и отдаю его людям — idlesign

Задачки на эрудированность

Откуда методы?

setUp()
tearDown()
SUnit (Smalltalk; с 1994 года)

Откуда методы?

assertTrue()
assertFalse()
assertEquals()
JUnit (Java; с 1998 года)

Откуда методы?

assertEqual()
assertIsNone()
assertIn()
PyUnit (Python; с конца 1999 года),
он же unittest (c 2001 года)

Питоничность

Применительно к стилю кода.
Использование характерных особенностей языка, позволяющее сохранить и подчеркнуть его сильные стороны, такие как лаконичность и лёгкость прочтения.

Переводчик на Питон

assertIn(a, b)
assert_in(a, b)
assertLessEqual(a, b)
assert_lte(a, b)
assertEqual(a, b)
assert_equal(a, b)
assertNotEqual(a, b)
assert_not_equal(a, b)
Testify — A more pythonic testing framework (c 2010 года)

Есть способ лучше

assertIn(a, b)
assert a in b
assertLessEqual(a, b)
assert a <= b
assertEqual(a, b)
assert a == b
assertNotEqual(a, b)
assert a != b
pytest (c 2007 года)

И doctest


def increment(x):
    """Добавляет 1 (единицу) к
    указанному x и возвращает результат.

    Примеры:

    >>> increment(1)
    2

    >>> increment(154)
    155

    """
    return x + 1


import doctest
doctest.testmod(verbose=True)
                                    

Trying:
    increment(1)
Expecting:
    2
ok
Trying:
    increment(154)
Expecting:
    155
ok
1 items had no tests:
    __main__
1 items passed all tests:
   2 tests in __main__.increment
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
Out[5]:
TestResults(failed=0, attempted=2)
                                    

pytest — это возможности

  • запуска тестов unittest, doctest, nose
  • контроля над выборкой тестов
  • досрочной остановки тестирования
  • перехода в режим отладки в pdb
  • профилирования
  • отправки результатов в pastebin-сервис
  • контроля над используемыми дополнениями*
  • и другие…

pytest — это удобства


# Параметризация.
# ===============
@pytest.mark.parametrize('username', ['user1', 'user2'])
def test_username(username):
    assert username == 'user1'

# Сравнение значений: ожидание — реальность.
# ==========================================
def test_sets():
    assert set('123') == set('12')
    # Extra items in the left set: '3'

def test_lists():
    assert [1, 2, 3] == [1, 4, 3]
    # At index 1 diff: 2 != 4

pytest — это фикстуры

Фикстура — подготовленное окружение, необходимое для запуска и стабильного выполнения теста.

Пример 1. Имитация MongoDB


@pytest.fixture(autouse=True)
def mock_mongo(monkeypatch):
    """Фикстура, подменяющая Mongo на mongomock."""
    monkeypatch.setattr(
        'mongoengine.connection._connection_settings', {
            'mydb': {
                'name': 'fake', 'username': '', 'password': ''
            }
    })
    monkeypatch.setattr(
        'mongoengine.connection.MongoClient', mongomock.MongoClient
    )

Пример 2. Фикстуры данных


@pytest.fixture
def read_fixture(request):
    """Считывает указанный файл из директории fixtures,
    находящейся в директории с тестовым модулем.

    """
    path_module = dirname(abspath(request.module.__file__))
    path_fixtures = join(path_module, 'fixtures')

    def read_it(fname):
        with open(join(path_fixtures, fname)) as f:
            return f.read()

    return read_it

def test_something(read_fixture):
    data = read_fixture('mydata.file')
    ...

Встроенные фикстуры

  • cache
  • capsys / capfd
  • doctest_namespace
  • pytestconfig
  • record_xml_property
  • monkeypatch
  • recwarn
  • tmpdir / tmpdir_factory

pytest — это сторонние дополнения

$ pip install pytest-*
  • aiohttp ∙ asyncio
  • bdd
  • benchmark ∙ timeit
  • blocker ∙ cagoule ∙ ordering
  • bugzilla ∙ gihub ∙ jira ∙ trello
  • cloud ∙ xdist
  • c ∙ cython
  • django ∙ flask ∙ tornado ∙ twisted
  • excel ∙ html ∙ json
  • factoryboy
  • flake ∙ pep-8 ∙ pep-257
  • mongo ∙ postgresql
  • qt ∙ selenium
  • и т.д. и т.д.

Ссылки

Спасибо за внимание!

Вопросы?

idlesign   idlesign   idlesign  

Эти слайды можно найти тут — http://bit.ly/ist_004