в этой статье,Генерал Юн Дуои Давайте учиться вместеPythonЛучшее визтестмодуль--Pytest,Основное обучение заключается в следующем:
Рекомендуется реализовать вручную.в этой статьеизнесколько примеров,чтобы углубить впечатление。Сначала вам нужно установитьpytest
。с большинствомPythonТот же пакет программного обеспечения,мы можемиспользовать pip от PyPI из Установить вpytest
。
$ python -m pip install pytest
Pytest
Команда теперь будет у насиз Доступен в среде установки。
pytest — это очень зрелая полнофункциональная среда тестирования Python. Ее основные функции заключаются в следующем:
Если вы когда-либо писали модульные тесты, вам следовало использовать Python серединаизunittest
модуль,У нашего сегодняшнего главного героя, Pytest, есть изображение точки.
В настоящее время в решении находится код наиболее популярных фреймворков тестирования. unittest
некоторые вопросы, они pytest
Это экология, плагин и Python сам по себе. тестовая система.
Как и большинство фреймворков, инструменты, предлагающие несколько шаблонов использования, безусловно, изменят процесс тестирования, и по ходу тестирования разработка определенных тестов может иметь последствия. Результаты испытаний и эффективность испытаний по-прежнему могут быть гарантированы.
большинствотествсе следуютОрганизация-Действие-Утверждение(Arrange-Act-Assert
)измодель。
Структура тестирования обычно связана с нашим тестированием.,Предоставить информацию в случае неудачи утверждения. Например,unittest
Множество полезных инструментов утверждения предоставляются «из коробки». Однако даже небольшой набор тестов требует значительного объема стандартного кода.
Напишите набор тестов, просто чтобы убедиться unittest
В проекте работает нормально. Возможно, мы захотим написать тест, который всегда проходит успешно, и тест, который всегда терпит неудачу.
# test_with_unittest.py
from unittest import TestCase
class TryTesting(TestCase):
def test_always_passes(self):
self.assertTrue(True)
def test_always_fails(self):
self.assertTrue(False)
Тогда ты сможешьиспользоватьunittest
изdiscover
Параметрыоткомандная строкасерединазапустить этитест。
$ python -m unittest discover
F.
============================================================
FAIL: test_always_fails (test_with_unittest.TryTesting)
------------------------------------------------------------
Traceback (most recent call last):
File "/.../test_with_unittest.py", line 9, in test_always_fails
self.assertTrue(False)
AssertionError: False is not True
------------------------------------------------------------
Ran 2 tests in 0.001s
FAILED (failures=1)
тест пройден,одинтестнеудача。Хотя мы доказалиunittest
действителениз,Но дальше нам понадобится:
unittest
импортироватьTestCase
добрыйTestCase
из ПодклассTryTesting
TryTesting
серединадлякаждыйтест Писатьодинметодunittest.TestCase
серединаиз self.assert*
в рамках методаутверждение。Хотя объем этого кода довольно велик,но потому что этолюбой тестнеобходимыйизминимумизкод,В конечном итоге мы все равно неоднократно пишем что-то вродеизкод。мы можемпроходить pytest
прямойиспользоватьPythonизassert
Ключевые слова для упрощения этого рабочего процесса。
# test_with_pytest.py
def test_always_passes():
assert True
def test_always_fails():
assert False
Нам не нужно использовать какой-либо импорт или классы, потому что мы можем использовать assert
Ключевые слова, которые нам тоже не нужно учить или запоминать unittest
все разные в self.assert*
метод. Если бы вы могли написать выражение, которое ожидало бы, что его значение будет "True"
,Такpytest
поможет намтестэто。
$ pytest
================== test session starts =============================
platform linux -- Python 3.7.3, pytest-5.3.0, py-1.8.0, pluggy-0.13.0
rootdir: /.../effective-python-testing-with-pytest
plugins: randomly-1.0.0, mock-1.2, cov-2.0.0
collected 2 items
test_with_pytest.py .F [100%]
======================== FAILURES ==================================
___________________ test_always_fails ______________________________
def test_always_fails():
> assert False
E assert False
test_with_pytest.py:5: AssertionError
============== 1 failed, 1 passed in 0.07s =========================
Pytest
показыватьизтест Результат тот же, что иunittest
другой,Отчет представлен ниже.
pytest
илюбой другойплагиниз Версияrootdir
,Или выполните поиск в каталоге Конфигурация.Вывод аналогиченunittest
изпосле синтаксисаизрезультаттестсостояние:
.
выражатьтестпроходить。На провализтест,Сообщить о сбое Дават подробнее。существоватьвышеизпримерсередина,тестнеудачада因дляassert False
Всегданеудача。
Вот еще несколько примеров краткости утверждений.
def test_uppercase():
assert "loud noises".upper() == "LOUD NOISES"
def test_reversed():
assert list(reversed([1, 2, 3, 4])) == [4, 3, 2, 1]
def test_some_primes():
assert 37 in {
num
for num in range(1, 50)
if num != 1 and not any([num % div == 0 for div in range(2, num)])
}
Pytest
изкоэффициент кривой обученияunittest
Быть поверхностным,Потому что нам не нужно изучать новоеизструктура。вернобольшинство人Приходить说assert
тест Дажелегко понять。
Наши тесты часто опираются на фрагменты данных некоторых объектов кода. существовать unittest
, мы можем извлечь эти зависимости в setUp()
и tearDown()
методсередина,Таким образом, каждый тест в классе сможет их использовать. но сделай это,может быть непреднамереннымсерединаделатьтестконкретномуданныеили объектизполностью зависим от“Скрытый”。
Со временем неявные зависимости могут привести к сложному беспорядку в коде, который нам придется разбирать, чтобы понять наши тесты. Тесты должны помочь нам сделать наш код более понятным. Если сам тест труден для понимания, то у нас могут быть проблемы!
Pytest
взятыйдругойизметод。этогиднасруководитьявныйЗаявление о зависимости,потому чтоfixture[1]из Доступность,Эти Заявление о зависимостивсе еще Может Тяжелыйиспользовать。**pytest fixture
длятест Создание комплектаданныеилитест Двойная копияилиисходныйизменятьнекоторый Статус системыизфункция. Любой, кто хочет использоватьfixture
Тесты это вседолженявныйприниматьэтокакпараметр**,Поэтому зависимости всегда объявляются заранее.
Fixture
Достаточно хорошоиспользоватьдругойfixture
,Объявите их также как зависимости. То есть со временем,fixture
может стать громоздкимимодульизменять。Хотя это будетfixture
вставлятьприезжатьдругойfixture
из Способность обеспечивает огромныеизгибкость,Но по мере роста набора тестов,Это также усложняет управление зависимостями.
По мере роста набора тестов мы можем обнаружить, что хотим запустить только несколько тестов для какой-либо функции. pytest
предоставил Некоторыйметод。
pytest
Ограничить запуски только полными именами, соответствующими определенному выражению.изтест。Можетиспользовать -k
параметр для завершения этой операцииpytest
будет запускать только тесуществоватькогдав предыдущем каталогеизтест。pytest
Может Сумкавключатьилиисключатьнас Конечноправедныйизконкретные категорииизтест。мы можемиспользовать-m
параметрчтобы добиться этоготочка。Pytest
Можетдлятестсоздаватьотметка,или пользовательские этикетки. Тест может иметь несколько тегов,Их можно использовать для детального контроля над тем, какой тест выполняется.
Когда вы тестируете функции, которые обрабатывают эти данные или просто преобразуют, вы можете найти множество похожих тестов, и они могут отличаться только входными или выходными данными тестируемого кода. Это требует дублирования тестового кода, что иногда скрывает поведение, которое мы пытаемся протестировать.
Unittest
Предоставляет возможность объединить несколькотестсобран водинизметод,Но в отчете о результатах он не отображается как отдельный изтест. Если тест не пройден,Все остальные прошли,Таквсеиндивидуальныйтест组все ещевстреча返回одиннеудачаизрезультат。Pytest
обеспечил себяизрешение,Каждый тест может пройти или не пройти независимо.
Pytest
лучшийизэкология этоэтоверно Конечносистемаи Шиничиточкаиз Функция обогащения,Почти любую программу можно взломать и модифицировать. поэтому,pytest
изиспользовать Домохозяйство развито.один Богатыйизоно работаетплагинизэкосистема。
Хотя некоторыеpytest
плагинсосредоточиться на конкретныхизрамка,нравитьсяDjango[2],Но другой разъем работает с большинством тестовых наборов.
Pytest fixtures
Это способ предоставить данные, тестовые двойники или настройки состояния для тестов.。Fixtures
да Может Вернуть несколько чиселценитьизфункция。каждый зависит отfixture
изтестдолжен明правильныйпринимать Долженfixture
какпараметр。
написать функцию format_data_for_display()
,Используется для обработки возврата конечных точек API. Эти данные представляют собой список людей из,У каждого есть имя, фамилия и должность. Функция должна вывести список строк из,Сюда входят полное имя каждого человека, двоеточие и титул. Следующий код.
def format_data_for_display(people):
... # Implement this!
def test_format_data_for_display():
people = [
{
"given_name": «Юнь Дуоцзюнь»,
"family_name": "Python",
"title": «Старший инженер-алгоритмист»,
},
{
"given_name": «маленькая обезьянка»,
"family_name": "Python",
"title": "Руководитель проекта",
},
]
assert format_data_for_display(people) == [
«Юнь Дуоцзюнь Python: Старший инженер-алгоритмист",
"маленькая обезьянка Python: Руководитель проекта",
]
Теперь предположим, что нам нужно написать еще одну функцию, преобразующую данные в значения, разделенные запятыми, для использования в Excel. Этот тест будет очень похож.
def format_data_for_excel(people):
... # Implement this!
def test_format_data_for_excel():
people = [
{
"given_name": «Юнь Дуоцзюнь»,
"family_name": "Python",
"title": «Старший инженер-алгоритмист»,
},
{
"given_name": «маленькая обезьянка»,
"family_name": "Python",
"title": "Руководитель проекта",
},
]
assert format_data_for_excel(people) == """
given,family,title
Юн Дуоцзюнь, Python, старший инженер-алгоритм
маленькая обезьянка, Python, менеджер проекта
"""
Что, если мы обнаружим, что пишем несколько тестов, используя одни и те же базовые тестовые файлы?,Так Можетиспользоватьодинfixture
,Собрать повторяющиеся изданные в одну функцию,использовать@pytest.fixture
Приходитьвыражать Долженфункциядаодинpytest
изfixture
。
import pytest
@pytest.fixture
def example_people_data():
return [
{
"given_name": «Юнь Дуоцзюнь»,
"family_name": "Python",
"title": «Старший инженер-алгоритмист»,
},
{
"given_name": «маленькая обезьянка»,
"family_name": "Python",
"title": "Руководитель проекта",
},
]
Вы можете прочитать это как параметрдобавить вприезжатьтестсередина Приходитьиспользовать Долженfixture
。этоизценить Воляда Долженfixture
функцияизвозвращаемое значение。
def test_format_data_for_display(example_people_data):
assert format_data_for_display(example_people_data) == [
«Юнь Дуоцзюнь Python: Старший инженер-алгоритмист",
"маленькая обезьянка Python: Руководитель проекта",
]
def test_format_data_for_excel(example_people_data):
assert format_data_for_excel(example_people_data) == """
given,family,title
Юн Дуоцзюнь, Python, старший инженер-алгоритм
маленькая обезьянка, Python, менеджер проекта
"""
Теперь каждый тест значительно сокращен,Также необходимо четко проследить, от чего это зависит.,должен Даватьfixture
ростодинспецифическийизимя。так,В будущем можно будет написать новый итест,Быстро определите, хотите ли вы этого.
Fixture
подходящийиспользовать Ю Чусинсуществоватьмногоиндивидуальныйтестсерединаиспользоватьизтакой жеизданныеили объект,Но он не подойдет тем, кому нужно внести небольшие изменения в данные тестизтеста. Потому что это добавляет уровень косвенности,существоватьтестнаборсерединаприсоединитьсяfixture
Чаще, чем присоединениеданныеили объектвозможный Даже Плохой。
когданайди себясуществоватьвсеиндивидуальныйпроектсерединанеоднократноиспользоватькто-тоfixture
час,мы можем Воляfixture
оттестмодульдвигатьсяприезжать Даже Проходитьиспользоватьизfixture
Связанныймодульсередина。так Сразуможет бытьэтоихимпортироватьприезжатьлюбойнуждатьсяэтоихизтестмодульсередина。
Pytest
существоватьвсеиндивидуальный Оглавлениеструктурасередина Находитьconftest.py
модуль。каждыйconftest.py
для pytest
Найти его можно в дереве файлов Конфигурация. Может находиться во всем файле и в родительском каталоге и в любом подкаталоге и спользовать в определенном conftest.py
середина Конечноправедныйизлюбойfixture
。этотдаодиннаиболее широко распространенныйиспользоватьизfixture
изхорошее место。
Pytest
середина Можетиспользовать@pytest.fixture
装饰器Приходить装饰одинметод,Украшенный метод из имени метода может быть передан в тестовый метод в качестве параметра. Операцию инициализации перед тестированием можно завершить таким образом.,Также возможно вернуть функцию данных Даваттест.
import pytest
class TestFixture:
@pytest.fixture(scope='function')
def example_people_data():
return [
{
"given_name": «Юнь Дуоцзюнь»,
"family_name": "Python",
"title": «Старший инженер-алгоритмист»,
},
{
"given_name": «маленькая обезьянка»,
"family_name": "Python",
"title": "Руководитель проекта",
},
]
def test_format_data_for_display(example_people_data):
assert format_data_for_display(example_people_data) == [
«Юнь Дуоцзюнь Python: Старший инженер-алгоритмист",
"маленькая обезьянка Python: Руководитель проекта",
]
Разделить по размеру сферы действия,Они есть:session>module>class>function
。
@pytest.fixture(scope='function') # область действия Значение по умолчанию — функция
function
функцияилиметодуровень Всевстречаодеялонастраиватьиспользоватьclass
добрыйуровеньнастраиватьиспользоватьодин разmodule
модульуровеньнастраиватьиспользоватьодин разsession
дамногоиндивидуальныйдокументнастраиватьиспользоватьодин раз,Можетчерез.py
документнастраиватьиспользовать,каждый.py
ФайлmoduleВы можете проверить область видимости с помощью следующего скрипта:
Изменяя область видимости из значения перечисления,Вы можете увидеть эффект,Можетсмотретьприезжатьprint('Вызов метода fillna')
существоватьдругойизscopeПараметры Вниз,Количество распечаток разное.
import pytest
@pytest.fixture(scope='function')
def example_people_data():
return [
{
"given_name": «Юнь Дуоцзюнь»,
"family_name": "Python",
"title": «Старший инженер-алгоритмист»,
},
{
"given_name": «маленькая обезьянка»,
"family_name": "Python",
"title": "Руководитель проекта",
},
]
class TestFixture:
def test_format_data_for_display(example_people_data):
assert format_data_for_display(example_people_data) == [
«Юнь Дуоцзюнь Python: Старший инженер-алгоритмист",
"маленькая обезьянка Python: Руководитель проекта",
]
Если вы хотите, чтобы каждый тестовый вариант использования был добавлен вfixture
Функция,Так Можетиспользовать@pytest.fixture
визautouse
параметр,autouse='true'
则встреча自动应использоватьприезжать Местооно работаетпримерсередина。
вышеодин案примердасуществоватьтакой жеодин.py
документсередина,многоиндивидуальныйиспользоватьпримернастраиватьиспользоватьодинданные Образецexample_people_data
,Если существует несколько файлов .pyiz, вам нужно вызвать этот dataiz,Тогда вы не сможете записать данные в вариант использования.
На этом этапе должен быть файл конфигурации.,Отдельное управление некоторыми предустановленными сценариями работы.,pytestв Чтение по умолчаниюconftest.py
виз Конфигурация
conftest.py
одеялоpytest视дляодинместныйплагин Библиотека,в целомиспользовать Вscope='session'
уровеньизfixture
。
использоватьconftest.py
изправило:
conftest.py
Это имя файла фиксированоиз,нельзя изменитьconftest.py
и бежатьиспользоватьпримерсуществоватьтакой жеодин Сумка Вниз,и Должен Сумкасередина Должно быть__init__.py
документconftest.py
,pytest автоматически загрузится,В какой пакет мне его положить?,Это действительно в рамках этого пакета.Fixture
из Другойодиниспользовать途даЗащитите доступ к ресурсам。Предположим, мы обработалиAPIнастраиватьиспользоватьизкод编Писать Понятноодинтестнабор,и хотите убедиться, что набор тестов не выполняет никаких реальных сетевых вызовов,Несмотря на тотест Случайно выполнил настоящийиз网络настраиватьиспользоватькод。Pytest
предоставилодинmonkeypatch[3] изfixture
заменить значениеи Поведение,Вы можете использовать его для достижения отличных результатов:
# conftest.py
import pytest
import requests
@pytest.fixture(autouse=True)
def disable_network_calls(monkeypatch):
def stunted_get():
raise RuntimeError("Network access not allowed during testing!")
monkeypatch.setattr(
requests,
"get",
lambda *args,
**kwargs: stunted_get())
в conftest.py
помещен в disable_network_calls()
и добавить autouse=True
вариант, мы можем гарантировать, что сетевые вызовы будут отключены в каждом тесте для всего пакета. любой вызов выполнения requests.get()
Тесты кода запустят RuntimeError, указывающий на неожиданный сетевой вызов.
В любом большом наборе тестов некоторые тесты неизбежно будут медленными. Например, у них может быть тест, время ожидания которого по какой-либо причине истекает, и при попытке быстро выполнить новую функцию было бы неплохо избежать запуска всех медленных тестов.
Pytest
Можетдлятест Определить категории,И укажите опцию включения или исключения категорий при запуске пакета. Мы можем использовать любое число категорий, чтобы отметить тест.
Маркировка тестов полезна для категоризации тестов по подсистемам или зависимостям. Например, если для некоторых тестов требуется доступ к базе данных, вы можете создать @pytest.mark.Database_access
отметка.
намекать:因длямы можем Даватьнасизотметкаростлюбойимя,Поэтому легко набрать или неправильно запомнить имя отметкаиз,
pytest
Для тегов, которые он не распознает, будет выдано предупреждение. Даватьpytest
команда плюс--strict-markers
Параметры Можетубеждатьсясуществоватьpytest
Конфигурациясерединазарегистрироватьсятестсерединаизвсеотметка Все。если бы тольконасиметьлюбой未зарегистрироватьсяизотметка,Все это помешает нам запустить тест.
Если вы хотите запускать только те, которым требуется доступ к библиотеке данных, изтестируйте,Такмы можемиспользоватьpytest -m database_access
бежатьвсеизтест。мы можемиспользоватьpytest -m "not database_access"
Запустить, кроме необходимыхданные Библиотекадоступизтест。насдаже Можетиспользоватьautouse fixture
ограничиватьданные Библиотекаиздоступ,Только для тех, кто отмечен знакомdatabase_access
изтест。
Некоторыйплагинпроходить Защитите доступ к ресурсамрасширятьотметкаиз Функция。pytest-django[4]плагинпредоставилодинdjango_db
отметка.любой没иметьэтотиндивидуальныйотметкаизтестсуществоватьпытатьсядоступданные Библиотекачас Всевстречанеудача。Нет.одинпытатьсядоступданные БиблиотекаизтествызоветDjangoтестданные Библиотекаизсоздавать。
добавить в django_db
Требование тегирования вынуждает вас явно объявлять зависимости, т. е. вы можете запускать независимые от базы данных тесты быстрее, потому что pytest -m "not django_db"
Не позволит тесту инициировать создание базы данных. Это экономит много времени.
pytest
предоставил Некоторый Прямо из коробкииспользоватьизотметка.
skip
:Пропустить безоговорочнотестskipif
:Если выражение имеет значение true, пропустите его.тестxfail
:Конечнотестнеудача,Если решение не удалось,Результаты всего тура теста все равно пройдутparametrize
(Уведомлениезаклинание):создаватьмногоиндивидуальныйдругойценитьизтесткогдапараметрМожетпроходитьбегатьpytest --markers
Посмотреть полностьюизpytest
отметкасписок。
Ранее в этой статье,нассмотретьприезжать Понятнонравитьсячтоиспользоватьpytest fixtrue
проходить Извлечение общих зависимостей(fixture
содержание)уменьшитькодповторить。такой жечас Также упомянитеприезжать Понятноодинfixtrue
不подходящийиспользоватьиз Состояние:когдаиметь输入и输出略иметьдругойизтестчас,Сразу不Таконо работает Понятно。этотчас Может**parametrize**[5]одинокийтест Конечноправедный,иpytest
встреча根据指Конечноизпараметрсоздаватьтестиз Варианты。
Напишите функцию, определяющую, является ли строка палиндромом. Начальный набор тестов может выглядеть следующим образом.
def test_is_palindrome_empty_string():
assert is_palindrome("")
def test_is_palindrome_single_character():
assert is_palindrome("a")
def test_is_palindrome_mixed_casing():
assert is_palindrome("Bob")
def test_is_palindrome_with_spaces():
assert is_palindrome("Never odd or even")
def test_is_palindrome_with_punctuation():
assert is_palindrome("Do geese see God?")
def test_is_palindrome_not_palindrome():
assert not is_palindrome("abc")
def test_is_palindrome_not_quite():
assert not is_palindrome("abab")
За исключением двух последних тестов, все остальные тесты имеют одинаковую структуру.
def test_is_palindrome_<in some situation>():
assert is_palindrome("<some string>")
Можетиспользовать@pytest.mark.parametrize()
существоватьэтотиндивидуальныйструктурасерединазаполнятьдругойизценить,Значительно сокращен тесткод.
@pytest.mark.parametrize("palindrome", [
"",
"a",
"Bob",
"Never odd or even",
"Do geese see God?",
])
def test_is_palindrome(palindrome):
assert is_palindrome(palindrome)
@pytest.mark.parametrize("non_palindrome", [
"abc",
"abab",
])
def test_is_palindrome_not_palindrome(non_palindrome):
assert not is_palindrome(non_palindrome)
parametrize()
из Нет.одинпараметрдаодинразделенные запятымиизпараметрстрока имени。второйпараметрдаодинпредставлятьпараметрценитьиз Предокилиодинокийценитьизсписок。Можетдальшепараметризменять,Объедините все тесты в один тест.
@pytest.mark.parametrize("maybe_palindrome, expected_result", [
("", True),
("a", True),
("Bob", True),
("Never odd or even", True),
("Do geese see God?", True),
("abc", False),
("abab", False),
])
def test_is_palindrome(maybe_palindrome, expected_result):
assert is_palindrome(maybe_palindrome) == expected_result
Это не только сокращает код,И использовать параметризацию отделяет поведение тестовыхоттестов.,Таким образом, вы можете четко знать, что делает тест!
Каждый раз при реализации кода переключается на среду тестового кодирования.,Будут некоторые накладные расходы,И очень медленно.
Как уже говорилось ранее, при беге тестиз,Вы можете идентифицировать и отфильтровать тест. Если вы хотите увеличить скорость теста,Так Сразу很иметь必要知道哪些тест Может Обеспечить максимумизулучшать。Pytest
Может Автоматическая записьтестчасмежду,и сообщить о самом медленномизtop nиндивидуальныйтест。
Давать pytest
команда плюс --durations
Параметры Пучокпродолжительностьотчет плюсприезжатьтестрезультатвнутри。--durations
приниматьодинвсе数добрый型n,И сообщит о самом медленном времени тестирования. Содержание отчета соответствует результатам теста.
$ pytest --durations=3
3.03s call test_code.py::test_request_read_timeout
1.07s call test_code.py::test_request_connection_timeout
0.57s call test_code.py::test_database_read
======================== 7 passed in 10.06s ==============================
Каждый тест, отображаемый в отчете о продолжительности, является ускоренным проектом, поскольку он занял больше времени, чем общее среднее значение.
Уведомление,Некоторые тесты могут иметь невидимые затраты на настройку. Мы упоминали ранее,Нет.один标иметьdjango_db
изтествызоветDjangoтестданные Библиотекаизсоздавать。продолжительность Отчет отражает триггерданные Библиотекасоздаватьизтестсерединанастраиватьданные Библиотекаизчасмежду,Это может ввести в заблуждение.
Ранее в этой статье,已经Понятно解Понятно Некоторыйиметь价ценитьизpytest
плагин,Мы можем изучить эти и некоторые другие плагины более подробно ниже.
pytest-randomly[6]Делать Понятно一件смотреть似简单但很иметь价ценитьизиметь значение:это迫делатьтестслучайным образомиз Запускать последовательно。
Таким образом, вы можете обнаружить те, которые зависят от запуска изтеста в определенном порядке.,этот意味СэтоихвернодругойтестиметьодинЗависимости с состоянием。нас不太возможныйсуществоватьpytest
серединаот Начни строить с нулятестнабор,это Дажеиметьвозможный发生существоватьнасмигрироватьприезжатьpytest
изтестнаборсередина。
Плагин напечатает начальное значение в описании конфигурации, которое можно использовать для запуска тестов в том же порядке при попытке устранить проблему.
Если измерить степень покрытия тестом достижения кодиз,насвозможныйвстречаиспользоватьcoverage[7]Сумка。pytest-cov[8]интегрированный Понятноcoverage
,Месток Можетбегатьpytest --cov
Приходите и посмотритетестотчет о покрытии。
pytest-django[9]для обработкиDjangoтестпредоставил Некоторыйоно работаетизfixtures
и marks
。нас Ранее в этой статьесмотретьприезжать Понятноdjango_db
отметка,иrf fixture
предусмотреноDjangoизRequestFactory[10]Примеризпрямойдоступ。settings fixture
предоставилодинбыстрыйнастраиватьиликрышкаDjangoнастраиватьизметод。эта параDjangoтест效率даодиночень большойизпродвигать!
pytest
Можетиспользовать Приходитьбегать传统единицатестза пределами диапазонаизтест。Поведение Стимулируйте развитие(BDD)Поощрять писать можноизиспользоватьсемья Поведениеиожидатьиз Описание на чистом языке,Тогда ты сможешьиспользоватьэто Приходить决Конечнода否выполнитьодинособенный Конечноиз Функция。pytest-bdd[11]помощьнасиспользоватьGherkin[12]длянасизкод编Писать Функциятест。
мы можемпроходитьэтотиндивидуальныйширокоизСписок сторонних плагинов[13]查смотреть哪些другойплагин Можетиспользовать Вpytest
。
данные Наука и промышленность,особенно ускорение,Обычная ошибка — это результат отсутствия написания модульного теста. По крайней мере, вы можете проверить, нормальный ли ввод.,Фактически, большинство научных проектов данных представляют собой отданные процессы обработки.
Проекты разные, но выполнение некоторых общих тестов тоже отличается.
#catch missing values assert
df['column'].isna().sum()<1
# check there is no duplicate
assert len(df['id'].unique())==df.shape[0]
assert df.groupby(['date','id']).size().max()==1
# have data for all ids?
assert df['id'].unique().shape[0] == len(ids)
# function returns have shapes as expected
assert all([some_funtion(df).shape == df[0].shape for df in dfs])
assert df.groupby('date')['percentage'].sum()==1
assert all (df['percentage']<=1)
assert df.groupby('name')['budget'].max()<=1000
d6tjoin[14]Можетисследовать Качество соединения。
assert d6tjoin.Prejoin([df1,df2],['date','id']).is_all_matched()
assert preprocess_function("name\t10019\n")==["name",10019]
assert preprocess_missing_name("10019\n") is None
assert preprocess_text("Do you Realize those are genetically modified food?" ) == ["you","realize","gene","modify","food"]
Написать примеры тестов pytest очень просто, достаточно следовать следующим правилам:
# -*- coding:utf-8 -*-
# pytest1.py
import pytest
@pytest.fixture(scope='function')
def setup_function(request):
def teardown_function():
print("teardown_function called.")
request.addfinalizer(teardown_function) # Эта встроенная функция выполняет работу по демонтажу
print('setup_function called.')
@pytest.fixture(scope='module')
def setup_module(request):
def teardown_module():
print("teardown_module called.")
request.addfinalizer(teardown_module)
print('setup_module called.')
@pytest.mark.website
def test_1(setup_function):
print('Test_1 called.')
def test_2(setup_module):
print('Test_2 called.')
def test_3(setup_module):
print('Test_3 called.')
assert 2==1+1 # Подтвердите, соответствуют ли результаты теста ожидаемым, с помощью утверждения утверждения.
этотвнутри补充одинsetup
иteardown
Знания, связанные с эксплуатацией。
Следующая статьясерединаunittestвиспользоватьпрефикси Заднийsetup
иteardown
очень хорошийиспользовать,Выполняйте его перед началом каждого варианта использования и после его завершения.
setup
,Выполнить перед тестовой функцией или классом,Полная подготовка,Например, ссылка на библиотеку данных, тестированные, открытый файл и т. д.teardown
,Выполнить после тестовой функции или класса,Полные отделочные работы,Например, отключение ссылки на библиотеку данных, переработку ресурсов памяти и т. д.fixture
функциясерединапроходитьyield
выполнитьsetup
иteardown
Функциякогда然还иметь Даже СтаршийточкаизsetupClass
иteardownClass
,Нужно сотрудничать@classmethod
Декораторы вместеиспользовать,При автоматизации селена из,Его эффективность особенно выдающаяся,Вы можете запустить браузер один раз, чтобы выполнить несколько вариантов использования.
Pytest
рамкатакжеиметьдобрый似Вsetup
иteardown
изграмматика,И есть больше, чем просто эти четыре
Firture
относительноsetup
иteardown
Приходить说应Должениметьк Вниз几точка Преимущества
setup
иteardown
этот几индивидуальныйжизньимяconftest.py
Конфигурациявнутри Можетвыполнитьданныеобщий,ненужныйimport
Сразу能自动找приезжать Некоторый Конфигурацияscope="module"
Можетвыполнитьмногоиндивидуальный.py
черездокументобщийпрефикс, Каждыйодин.py
документнастраиватьиспользоватьодин разscope="session"
квыполнитьмногоиндивидуальный.py
черездокументиспользоватьодинsession
Приходить完成многоиндивидуальныйиспользоватьпримерУ вас могут возникнуть такие вопросы,Сейчас все используют такие инструменты, как PycharmизIDE.,Зачем вам нужно научиться запускать изпараметры в командной строке?
Pytest
рамкадаодинтестрамка,Если вам нужно интегрировать его в Дженкинс,,Вам нужно использовать командную строку для его выполнения,Иногда вам нужно выполнить несколько вариантов использования,Удобнее использовать файлы командной строки.
Pytest
Можетсуществоватькомандная строка执行,При выполнении из в командной строке,Вы можете привести много параметров,Вниз面介绍几种常использоватьприезжатьизпараметриспользовать Закон:(использоватьpytest --help
Можетсмотретьприезжатьжизнь令параметриз Справочная документация)
Использование: pytest или py.test прочитает все файлы, классы, методы и функции, которые соответствуют правилам в текущем пути, и выполнит их.
v
параметрРаспечатайте подробную информацию журнала работы, чтобы облегчить обнаружение проблемы.
-s
параметрРезультаты можно вывести на консоль. Если в коде для вывода информации используется оператор печати, без этого параметра консоль не будет отображать содержимое печати.
-k
параметрИспользуйте этот параметр, чтобы указать вариант использования, соответствующий требованиям для запуска. Использование следующее:
pytest -k "имя класса"
pytest -k "имя метода"
pytest -k «Имя класса and not имя метода"
Уведомление: -k
параметрс последующимиз Кавычки могут быть толькоиспользоватьдвойные кавычки""
,не могуиспользоватьодинарная кавычка''
,В противном случае вариант использования не будет распознан.,При запуске будет сообщено об ошибке
-x
параметрЕсли вариант использования не выполняется или утверждение не выполняется, он немедленно прекращает выполнение и не выполняет последующие варианты использования.
--maxfail
параметрУстановите количество тестовых случаев, которые могут завершиться неудачно. При превышении этого порога выполнение будет остановлено.
pytest --maxfail=num
,неудачаиспользоватьпример数>=num
час,Хватит бежать
-m
параметрЗапуск всех вариантов использования, содержащих определенный тег, в соответствии с именем тега.,нуждатьсясуществоватьтестиспользоватьпримервыше Вседобавить декоратор@pytest.mark.отметкаимя
。использовать-m
Параметры,Можетделать表达式指Конечномногоиндивидуальныйотметкаимя。использовать-m "mark1 and mark2"
Можеттакой жечасвыбиратьсерединаприноситьиметьэтот两индивидуальныйотметкаизвсетестиспользоватьпример。использовать-m "mark1 and not mark2"
则встречавыбиратьсерединаприноситьmark1
отметка И не приноси этоmark2
отметкаизтестиспользоватьпример,использовать-m "mark1 or mark2"
则встречавыбиратьсерединаприноситьиметьmark1
илиmark2
извсетестиспользоватьпример。
Теги вариантов использования используются следующим образом:
import pytest
@pytest.mark.mark1
@pytest.mark.mark2
def test_a002(self):
print('this is test_a002 method')
использовать-m
параметрбегатьчас,Возможно, что намекать
pytest
предоставляет основной наборизпроизводительные силы Функция,Может фильтровать и оптимизировать тест,Также существует гибкая система изплагина.,Можетдальше扩展其价ценить。несмотря ни на чтонасдаиметьодиногромныйизнаследиеunittest
набор,Все еще нужно начать новый проект?,pytest
Все能длянас Предложите многоизпомощь。
существоватьв этой статье,Юн Дуоцзюнь и все научились использовать:
[1]
fixture: https://docs.pytest.org/en/latest/fixture.html
[2]
Django: https://www.djangoproject.com/
[3]
monkeypatch: https://docs.pytest.org/en/latest/monkeypatch.html
[4]
pytest-django: https://pytest-django.readthedocs.io/en/latest/
[5]
parametrize: http://doc.pytest.org/en/latest/example/parametrize.html
[6]
pytest-randomly: https://github.com/pytest-dev/`pytest-randomly
[7]
coverage: https://coverage.readthedocs.io/
[8]
pytest-cov: https://pytest-cov.readthedocs.io/en/latest/
[9]
pytest-django: https://pytest-django.readthedocs.io/en/latest/
[10]
RequestFactory: https://docs.djangoproject.com/en/3.0/topics/testing/advanced/#django.test.RequestFactory
[11]
pytest-bdd: https://pytest-bdd.readthedocs.io/en/latest/
[12]
Gherkin: http://docs.behat.org/en/v2.5/guides/1.gherkin.html
[13]
Список сторонних плагинов: http://plugincompat.herokuapp.com/
[14]
d6tjoin: https://github.com/d6t/d6tjoin