Тестирование

TODO В 2023 году рассказ про pytest оказался скомканным, скорее всего стоит только упомянуть его в числе прочих «больших» инструментариев.

(Дополнительно: Оффлайн-лекция позапрошлого года про квазиобъекты)

TODO softwaretestingfundamentals is dead ☹

много теории без питона тут

Модульное тестирование в Python

Doctest

doctest: тест = диалог с python-интерпретатором

Пример использования doctest

Поэтому только кратко:

  1. Модуль
  2. Тестируем вручную из командной строки
  3. Добавляем диалог as is в docstring:
  4. Тестирование: python3 -m doctest Moo.py

  5. Отчёт (с успешными тестами): python3 -m doctest -v Moo.py

  6. Тестирование исключений
    • Вообще говоря, важны только три строчки (сама команда, первая строка и сообщение с исключением), остальные можно выкинуть
  7. Перенос тестов во внешний текстовый файл,

    • например, в .rst

    • этот файл отлично включается в Sphinx-документацию
    • Запуск python3 exttest.py -v:

      •    1    import doctest
           2    doctest.testfile("exttest.rst")
        

«Серьёзные» фреймворки

Как правило — реализация методологии xUnit

Fixture
Подготовка компонента к тесту: не все функции можно оттестировать сходу, иногда надо
  1. сначала что-то создать, открыть, запустить, … (set-up)

  2. провести тест
  3. удалить, закрыть, остановить, … это что-то (tear-down)

    • Такое одно что-то называется fixture
Test

Атомарная процедура тестирования. Как правило однократно сравнивает ожидаемый результат с полученным.

Case
Набор тестов для тестирования определённого свойства объекта. Подготавливаем окружение (fixtur-ы), изучаем заявленное свойство, в т. ч. в граничных условиях.
SubCase
Элемент множественного тестирования (например, при циклическом вызове теста на различных наборах данных)
Suite
Набор cases (на разные темы, разных больших частей, разных уровней, несовместимых с другим набором и т. п.)
Runner
Запускалка тестов, обработчик отчётов и т. п.

Модуль unittest

Принципы unittest:

Возможности:

Примеры использования

Квазиобъекты (mock)

Основные понятия:

Квазиобъект (mock object, mocker)

объект, создаваемый в процессе тестирования вместо «настоящего» объекта

  • Как правило, умеет всё сразу (его можно вызывать с любыми параметрами, обращаться к любым полям внутри него и т. п.)
  • Умеет отчитываться (такой-то метод был вызван так-то)
  • Свойства объекта и его полей (которые создаются автоматически как такие же квазиобъекты) — настраиваемые. Например, можно задать возвращаемые значения, значение некоторых полей, вызываемые исключения и т. п.
Патч (patch или monkey patch)
подмена на время теста полей реального объекта на квазиобъекты
  • Нередко обладает свойством самоудаляться по окончании теста. Например, патч оформляется как контекстный менеджер

Индикатор (sentinel)

уникальный объект, который передаётся в тестируемую подсистему, и по окончании теста должен продолжать существовать в неизменном виде и там, куда вы его положили ☺. Может выдерживать копирование и сериализацию / десериализацию.

  • Если индикатор в процессе тестирования удаляется, тест не пройден

unittest.mock

Тестовое покрытие

(тысячи их)

Модуль coverage

Пример

В репозитории примеров к лекции

«Большие» инструментарии

pytest

Статья на Хабре

Примеры инструментарив других уровней тестирования:

Тысячи их…

(если успеем) Пример использования pytest: pudb

PuDB — отладчик для питона

Соберём под него окружение:

[george@inspiron src]$ python3 -m venv init demo-pudb
[george@inspiron src]$ cd demo-pudb
[george@inspiron demo-pudb]$ . ./bin/activate
(demo-pudb) [george@inspiron demo-pudb]$ git clone https://github.com/inducer/pudb.git
Cloning into 'pudb'...
cd pudb
(demo-pudb) [george@inspiron pudb]$  ls
debug_me.py             example-theme.py  pudb                  setup.py
doc                     LICENSE           README.rst            test
example-shell.py        MANIFEST.in       requirements.dev.txt  try-the-debugger.sh
example-stringifier.py  manual-tests      setup.cfg             upload_coverage.sh
(demo-pudb) [george@inspiron pudb]$

Cоберём модуль:

(demo-pudb) [george@inspiron pudb]$ pip install -r requirements.dev.txt
Collecting codecov==2.0.5 (from -r requirements.dev.txt (line 1))
. . .
Successfully installed Pygments-2.2.0 argparse-1.4.0 . . .
(demo-pudb) [george@inspiron pudb]$ python setup.py build
running build
. . .
copying pudb/ui_tools.py -> build/lib/pudb
(demo-pudb) [george@inspiron pudb]$

(demo-pudb) [george@inspiron pudb]$ export PYTHONPATH=`pwd`/build/lib
(demo-pudb) [george@inspiron pudb]$ pytest
========================= test session starts =========================
platform linux -- Python 3.8.2, pytest-3.0.7, py-1.4.33, pluggy-0.4.0
rootdir: /home/george/src/demo-pudb/pudb, inifile:
plugins: mock-1.10.0, cov-2.4.0
collected 16 items

test/test_lowlevel.py ....
test/test_make_canvas.py .....
test/test_settings.py ..
test/test_source_code_providers.py ....
test/test_var_view.py .

====================== 16 passed in 0.22 seconds ======================

В этом проекте используется два дополнения к pytest:

Д/З

LecturesCMC/PythonDevelopment2024/10_Testing (последним исправлял пользователь FrBrGeorge 2024-06-08 19:43:52)