Учебное пособие по PyTest: Что такое PyTest? (с примерами)

⚡ Умное резюме

Pytest — это Python Фреймворк для тестирования, помогающий писать простые, масштабируемые тесты для баз данных, API и пользовательских интерфейсов. Он поддерживает фикстуры, параметризацию, маркеры, параллельное выполнение и подробные отчеты об утверждениях, от базовых модульных тестов до сложных функциональных тестов.

  • 🔘 Установка: Команда `pip install pytest` добавляет фреймворк, а `py.test -h` подтверждает установку, выводя справку.
  • ☑️ Обнаружение тестов: Pytest автоматически собирает файлы с именами test_*.py или *_test.py, а также методы, имена которых начинаются с test.
  • Утверждения: В обычных операторах assert при неудачной проверке отображается сообщение AssertionError с указанием сравниваемых значений.
  • 🧪 Светильники: Декоратор `@pytest.fixture` предоставляет многократно используемые данные настройки, которые передаются между файлами через файл `conftest.py`.
  • 🇧🇷 Выборочные запуски: Маркеры, фильтр подстрок -k и параметризация запускают целевые подмножества или один и тот же тест для множества входных данных.
  • 🤖 Рабочие процессы ИИ: Команды, занимающиеся машинным обучением, используют pytest для проверки конвейеров обработки данных и результатов работы моделей, а Copilot позволяет создавать тестовые примеры.

Учебное пособие по PyTest

Питест является одним из наиболее широко используемых фреймворков для тестирования. Python экосистема. Она обеспечивает краткость и читаемость тестового кода, автоматически обнаруживает тесты и развивается от первого утверждения до полноценного набора тестов для баз данных, API и пользовательских интерфейсов. В разделах ниже подробно описаны установка, утверждения, фикстуры, маркеры, параметризация и параллельное выполнение с практическими примерами.

Что такое Pytest?

Питест Это фреймворк для тестирования, который позволяет писать тестовый код, используя Python Язык программирования. Он помогает писать простые и масштабируемые тестовые сценарии для баз данных, API и даже пользовательских интерфейсов. Pytest используется в основном для написания тестов для API и масштабируется от простых модульных тестов до сложных функциональных тестов.

Почему стоит использовать Pytest?

К преимуществам pytest относятся, например, следующие:

  • С ним очень легко начать работать благодаря простому и понятному синтаксису.
  • Может запускать тесты параллельно.
  • Можно запустить конкретный тест или подмножество тестов.
  • Автоматически обнаруживает тесты.
  • Можно пропускать тесты.
  • Открытый исходный код.

Как установить Pytest

Ниже описан процесс установки pytest:

Шаг 1) Установить pytest можно с помощью приведенной ниже команды.

pip install pytest==2.9.1

После завершения установки вы можете подтвердить её с помощью следующей команды.

py.test -h

Это отобразит справку.

Установите pytest и просмотрите справку.

Первый базовый пример pytest

Теперь вы узнаете, как использовать pytest на простом примере.

Создайте папку study_pytest. В этой папке вы будете создавать тестовые файлы. Перейдите в эту папку в командной строке. Создайте в этой папке файл с именем test_sample1.py.

Создайте первый базовый тестовый файл pytest.

Вставьте приведенный ниже код и сохраните.

import pytest
def test_file1_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed"
def test_file1_method2():
	x=5
	y=6
	assert x+1 == y,"test failed" 

Запустите тест, используя команду ниже.

py.test

В результате вы получите следующий результат.

test_sample1.py F.
============================================== FAILURES ========================================
____________________________________________ test_sample1 ______________________________________
    def test_file1_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed"
E       AssertionError: test failed
E       assert 5 == 6
test_sample1.py:6: AssertionError

Результат выполнения теста pytest, завершившегося с ошибкой.

В файле test_sample1.py буква F обозначает ошибку, а точка (.) — успех. В разделе failures вы можете увидеть неудачно выполненный метод (или методы) и строку ошибки. Здесь x==y означает 5==6, что неверно.

Далее вы узнаете об утверждениях в pytest.

Утверждения в pytest

Утверждения в pytest — это проверки, которые возвращают либо статус True, либо False. В pytest, если утверждение в тестовом методе не выполняется, выполнение этого метода останавливается. Оставшийся код в этом тестовом методе не выполняется, и pytest переходит к следующему тестовому методу.

Примеры утверждений pytest:

assert "hello" == "Hai" is an assertion failure.
assert 4==4 is a successful assertion
assert True is a successful assertion
assert False is an assertion failure.

Обратите внимание на следующее.

assert x == y,"test failed because x=" + str(x) + " y=" + str(y)

Вместо приведенного ниже утверждения разместите этот код в функции test_file1_method1().

assert x == y,"test failed"

Запуск теста приведет к ошибке, поскольку AssertionError: тест не пройден x=5 y=6.

Как PyTest идентифицирует тестовые файлы и тестовые методы

По умолчанию pytest распознает только имена файлов, начинающиеся с определенного префикса. тестовое задание_ или заканчивая _контрольная работа в качестве тестовых файлов. Однако мы можем явно указать и другие имена файлов (объяснение позже). Pytest требует, чтобы имена тестовых методов начинались с тестВсе остальные имена методов игнорируются, даже если мы явно запрашиваем их выполнение.

Ознакомьтесь с примерами допустимых и недопустимых имен файлов pytest.

test_login.py - valid
login_test.py - valid
testlogin.py -invalid
logintest.py -invalid

Примечание: Да, мы можем явно указать pytest выбрать файлы testlogin.py и logintest.py.

Ознакомьтесь с примерами допустимых и недопустимых методов тестирования pytest.

def test_file1_method1(): - valid
def testfile1_method1(): - valid
def file1_method1(): - invalid	

Примечание: Даже если мы явно укажем file1_method1(), pytest не выполнит этот метод.

Запуск нескольких тестов из определенного файла и нескольких файлов

В настоящее время в папке study_pytest находится файл test_sample1.py. Предположим, у нас есть несколько файлов, скажем, test_sample2.py и test_sample3.py. Чтобы запустить все тесты из всех файлов в папке и подпапках, нам нужно просто выполнить команду pytest.

py.test

Эта команда выполнит поиск по всем файлам, имена которых начинаются с test_ и заканчиваются на _test, как в этой папке, так и в подпапках внутри неё.

Для запуска тестов только из определенного файла можно использовать `py.test`. .

py.test test_sample1.py

Запустите подмножество всего теста с помощью pytest.

Иногда нам не нужно запускать весь набор тестов. PyTest позволяет запускать только определенные тесты. Это можно сделать двумя способами:

  • Grouping названия тестов путем сопоставления подстрок.
  • Grouping тестов с использованием маркеров.

У нас уже есть файл test_sample1.py. Создайте файл test_sample2.py и добавьте в него следующий код.

def test_file2_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
def test_file2_method2():
	x=5
	y=6
	assert x+1 == y,"test failed"

Таким образом, на данный момент у нас имеется следующая информация.

• test_sample1.py
• test_file1_method1()
• test_file1_method2()
• test_sample2.py
• test_file2_method1()
• test_file2_method2()

Вариант 1) Запуск тестов путем сопоставления подстрок.

Чтобы запустить все тесты, в названии которых содержится method1, необходимо выполнить следующую команду.

py.test -k method1 -v
-k <expression> is used to represent the substring to match
-v increases the verbosity

Таким образом, выполнение команды `py.test -k method1 -v` даст следующий результат.

test_sample2.py::test_file2_method1 FAILED
test_sample1.py::test_file1_method1 FAILED

============================================== FAILURES ==============================================
_________________________________________ test_file2_method1 _________________________________________
    def test_file2_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E       AssertionError: test failed because x=5 y=6
E       assert 5 == 6
test_sample2.py:5: AssertionError

_________________________________________ test_file1_method1 _________________________________________
    @pytest.mark.only
    def test_file1_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E       AssertionError: test failed because x=5 y=6
E       assert 5 == 6
test_sample1.py:8: AssertionError

================================= 2 tests deselected by '-kmethod1' ==================================
=============================== 2 failed, 2 deselected in 0.02 seconds ===============================

Здесь, ближе к концу, вы можете увидеть... 2 теста отменены с помощью '-kmethod1', которыми являются test_file1_method2 и test_file2_method2.

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

py.test -k method -v - will run all the four methods
py.test -k methods -v – will not run any test as there is no test name matches the substring 'methods'

Вариант 2) Запустить тесты по маркерам

PyTest позволяет задавать различные атрибуты для тестовых методов с помощью маркеров pytest, @pytest.mark. Чтобы использовать маркеры в тестовом файле, необходимо импортировать pytest в тестовые файлы. Здесь мы применим разные имена маркеров к тестовым методам и будем запускать определенные тесты в зависимости от этих имен. Мы можем определить маркеры для каждого имени теста, используя следующий код.

@pytest.mark.<name>.			

Мы определяем маркеры set1 и set2 для тестовых методов и будем запускать тесты, используя имена этих маркеров. Обновите тестовые файлы следующим кодом.

test_sample1.py

import pytest
@pytest.mark.set1
def test_file1_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)

@pytest.mark.set2
def test_file1_method2():
	x=5
	y=6
	assert x+1 == y,"test failed"

test_sample2.py

import pytest
@pytest.mark.set1
def test_file2_method1():
	x=5
	y=6
	assert x+1 == y,"test failed"
	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)

@pytest.mark.set1
def test_file2_method2():
	x=5
	y=6
	assert x+1 == y,"test failed"

Мы можем запустить отмеченный тест с помощью приведенной ниже команды.

py.test -m <name>
-m <name> mentions the marker name

Запустите py.test -m set1. Это запустит методы test_file1_method1, test_file2_method1 и test_file2_method2. Запуск py.test -m set2 запустит метод test_file1_method2.

Запуск тестов параллельно с помощью pytest

Обычно набор тестов содержит множество тестовых файлов и сотни тестовых методов, выполнение которых занимает значительное количество времени. Pytest позволяет запускать тесты параллельно. Для этого необходимо сначала установить pytest-xdist, выполнив команду, указанную ниже.

pip install pytest-xdist

Запускайте тесты параллельно с помощью pytest-xdist

Теперь вы можете запустить тесты с помощью следующей команды.

py.test -n 4

Здесь, -н Тесты запускаются с использованием нескольких рабочих процессов. В приведенной выше команде для выполнения тестов будет задействовано четыре рабочих процесса.

Pytest Светильники

Фикстуры используются, когда мы хотим выполнить некоторый код перед каждым тестовым методом. Таким образом, вместо того, чтобы повторять один и тот же код в каждом тесте, мы определяем фикстуры. Обычно фикстуры используются для инициализации подключений к базе данных, передачи базовых данных. URLи так далее. Метод помечается как фикстура pytest путем добавления к нему следующей маркировки.

@pytest.fixture

Метод тестирования может использовать фикстуру pytest, указав её в качестве входного параметра. Создайте новый файл test_basic_fixture.py со следующим кодом.

import pytest
@pytest.fixture
def supply_AA_BB_CC():
	aa=25
	bb =35
	cc=45
	return [aa,bb,cc]

def test_comparewithAA(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"

def test_comparewithBB(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed"

def test_comparewithCC(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"

Вот:

  • У нас есть фикстура с именем supply_AA_BB_CC. Этот метод возвращает список из трех значений.
  • Мы используем три метода тестирования, сравнивая результаты с каждым из значений.

Каждая из тестовых функций имеет входной аргумент, имя которого соответствует доступному фикстурному файлу. Затем Pytest вызывает соответствующий метод фикстурного файла, и возвращаемые значения сохраняются во входном аргументе, в данном случае это список [25,35,45]. Элементы списка затем используются в тестовых методах для сравнения. Теперь запустите тест и посмотрите результат.

 py.test test_basic_fixture
test_basic_fixture.py::test_comparewithAA FAILED                                                                                                                                                                                       
test_basic_fixture.py::test_comparewithBB PASSED                                                                                                                                                                                       
test_basic_fixture.py::test_comparewithCC FAILED
                                                                                                                                                                                       
============================================== FAILURES ==============================================
_________________________________________ test_comparewithAA _________________________________________
supply_AA_BB_CC = [25, 35, 45]
    def test_comparewithAA(supply_AA_BB_CC):
    	zz=35
>   	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"
E    AssertionError: aa and zz comparison failed
E    assert 25 == 35
test_basic_fixture.py:10: AssertionError

_________________________________________ test_comparewithCC _________________________________________
supply_AA_BB_CC = [25, 35, 45]
    def test_comparewithCC(supply_AA_BB_CC):
    	zz=35
>   	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
E    AssertionError: cc and zz comparison failed
E    assert 45 == 35
test_basic_fixture.py:16: AssertionError
================================= 2 failed, 1 passed in 0.05 seconds =================================

Тест test_comparewithBB проходит успешно, поскольку zz=BB=35, а два оставшихся теста не проходят.

Метод fixture имеет область видимости только в пределах тестового файла, где он определен. Если мы попытаемся получить доступ к fixture в другом тестовом файле, мы получим ошибку, указывающую на наличие fixture. 'supply_AA_BB_CC' не найден для методов тестирования в других файлах.

Чтобы использовать один и тот же фикстурный набор данных для нескольких тестовых файлов, мы создаём методы фикстуры в файле с именем conftest.py. Рассмотрим это на примере pytest, приведённом ниже. Создайте три файла: conftest.py, test_basic_fixture.py и test_basic_fixture2.py, содержащие следующий код.

conftest.py

import pytest
@pytest.fixture
def supply_AA_BB_CC():
	aa=25
	bb =35
	cc=45
	return [aa,bb,cc]

test_basic_fixture.py

import pytest
def test_comparewithAA(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"

def test_comparewithBB(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed"

def test_comparewithCC(supply_AA_BB_CC):
	zz=35
	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"

test_basic_fixture2.py

import pytest
def test_comparewithAA_file2(supply_AA_BB_CC):
	zz=25
	assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed"

def test_comparewithBB_file2(supply_AA_BB_CC):
	zz=25
	assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed"

def test_comparewithCC_file2(supply_AA_BB_CC):
	zz=25
	assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"

Pytest сначала будет искать фикстуру в тестовом файле, и если она не будет найдена, то будет искать её в файле conftest.py. Запустите тест с помощью команды `py.test -k test_comparewith -v`, чтобы получить результат, показанный ниже.

test_basic_fixture.py::test_comparewithAA FAILED  
test_basic_fixture.py::test_comparewithBB PASSED 
test_basic_fixture.py::test_comparewithCC FAILED 
test_basic_fixture2.py::test_comparewithAA_file2 PASSED 
test_basic_fixture2.py::test_comparewithBB_file2 FAILED 
test_basic_fixture2.py::test_comparewithCC_file2 FAILED

Параметризованный тест Pytest

Цель параметризации теста — запустить тест с несколькими наборами аргументов. Это можно сделать с помощью `@pytest.mark.parametrize`. Мы увидим это на примере pytest ниже. Здесь мы передадим три аргумента методу теста. Этот метод теста сложит первые два аргумента и сравнит результат с третьим аргументом. Создайте файл теста test_addition.py со следующим кодом.

import pytest
@pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)])
def test_add(input1, input2, output):
	assert input1+input2 == output,"failed"

Здесь метод test принимает три аргумента: input1, input2 и output. Он складывает input1 и input2 и сравнивает сумму с output. Давайте запустим тест с помощью команды `py.test -k test_add -v` и посмотрим результат.

test_addition.py::test_add[5-5-10] PASSED                                                                                                                                                                                              
test_addition.py::test_add[3-5-12] FAILED                                                                                                                                                                                              
============================================== FAILURES ==============================================
__________________________________________ test_add[3-5-12] __________________________________________
input1 = 3, input2 = 5, output = 12
    @pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)])
    def test_add(input1, input2, output):
>   	assert input1+input2 == output,"failed"
E    AssertionError: failed
E    assert (3 + 5) == 12
test_addition.py:5: AssertionError

Как видите, тесты проводились дважды: один раз проверялось, равно ли 5+5 ==10, а другой — равно ли 3+5 ==12.

test_addition.py::test_add[5-5-10] ПРОЙДЕНО

test_addition.py::test_add[3-5-12] ОШИБКА

pytest Xfail и Skip Tests

В некоторых ситуациях мы не захотим выполнять тест, или же... прецедент Это не имеет значения в конкретный момент времени. В таких ситуациях у нас есть возможность либо провалить тест, либо пропустить тесты. Проваленный тест будет выполнен, но он не будет учитываться как среди пройденных или проваленных тестов. Не будет никаких дополнительных действий. tracЕсли тест не пройден, отобразится сообщение eback. Мы можем отключать тесты с помощью @pytest.mark.xfail. Пропуститьping Отметка «тест» означает, что тест не будет выполнен. Мы можем пропускать тесты, используя @pytest.mark.skip. Отредактируйте файл test_addition.py, добавив следующий код.

import pytest
@pytest.mark.skip
def test_add_1():
	assert 100+200 == 400,"failed"

@pytest.mark.skip
def test_add_2():
	assert 100+200 == 300,"failed"

@pytest.mark.xfail
def test_add_3():
	assert 15+13 == 28,"failed"

@pytest.mark.xfail
def test_add_4():
	assert 15+13 == 100,"failed"

def test_add_5():
	assert 3+2 == 5,"failed"

def test_add_6():
	assert 3+2 == 6,"failed"

Вот:

  • test_add_1 и test_add_2 пропускаются и не будут выполнены.
  • Тесты test_add_3 и test_add_4 завершились с ошибкой (xfailed). Эти тесты будут выполнены и войдут в состав тестов, завершившихся с ошибкой (xfailed) или прошедших тест (xpassed). Никаких дополнительных тестов не будет. traceback для устранения неполадок.
  • Будут выполнены функции test_add_5 и test_add_6, при этом test_add_6 сообщит о сбое. traceback while test_add_5 passes.

Выполните тест с помощью команды `py.test test_addition.py -v` и посмотрите результат.

test_addition.py::test_add_1 SKIPPED
test_addition.py::test_add_2 SKIPPED
test_addition.py::test_add_3 XPASS
test_addition.py::test_add_4 xfail
test_addition.py::test_add_5 PASSED
test_addition.py::test_add_6 FAILED

============================================== FAILURES ==============================================
_____________________________________________ test_add_6 _____________________________________________
    def test_add_6():
>   	assert 3+2 == 6,"failed"
E    AssertionError: failed
E    assert (3 + 2) == 6
test_addition.py:24: AssertionError

================ 1 failed, 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.07 seconds =================

Результаты в формате XML

Мы можем создавать результаты тестирования в формате XML, которые затем можно передавать на серверы непрерывной интеграции для дальнейшей обработки. Это можно сделать с помощью команды `py.test test_sample1.py -v –junitxml=”result.xml”`. В файле `result.xml` будет записан результат выполнения теста. Пример файла `result.xml` приведен ниже.

<?xml version="1.0" encoding="UTF-8"?>
<testsuite errors="0" failures="1" name="pytest" skips="0" tests="2" time="0.046">
   <testcase classname="test_sample1" file="test_sample1.py" line="3" name="test_file1_method1" time="0.001384973526">
     <failure message="AssertionError:test failed because x=5 y=6 assert 5 ==6">
    @pytest.mark.set1
    def test_file1_method1():
    	x=5
    	y=6
       	assert x+1 == y,"test failed"
>      	assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
E       AssertionError: test failed because x=5 y=6
E       assert 5 == 6
         test_sample1.py:9: AssertionError
    </failure>
   </testcase>
   <testcase classname="test_sample1" file="test_sample1.py" line="10" name="test_file1_method2" time="0.000830173492432" />
</testsuite>

От Мы видим, что было проведено два теста, один из которых не прошёл. Ниже вы можете увидеть подробную информацию о каждом выполненном тесте. ярлык.

Фреймворк pytest для тестирования API

Теперь мы создадим небольшой фреймворк pytest для тестирования API. В качестве API здесь используется бесплатный сервис. reqres.inЭтот веб-сайт просто предоставляет тестируемый API и не хранит наши данные. Здесь мы напишем несколько тестов для следующих пунктов:

  • Приведён список некоторых пользователей.
  • Вход с использованием учетных записей пользователей.

Создайте файлы, указанные ниже, с предоставленным кодом. Во-первых, в файле conftest.py есть фикстура, которая будет предоставлять базовые данные. URL для всех методов тестирования.

import pytest
@pytest.fixture
def supply_url():
	return "https://reqres.in/api"

Далее, файл test_list_user.py содержит тестовые методы для вывода списка действительных и недействительных пользователей.

  • Функция test_list_valid_user проверяет корректность запроса пользователя и подтверждает правильность ответа.
  • Функция test_list_invaliduser проверяет наличие некорректного запроса пользователя и подтверждает полученный ответ.
import pytest
import requests
import json
@pytest.mark.parametrize("userid, firstname",[(1,"George"),(2,"Janet")])
def test_list_valid_user(supply_url,userid,firstname):
	url = supply_url + "/users/" + str(userid)
	resp = requests.get(url)
	j = json.loads(resp.text)
	assert resp.status_code == 200, resp.text
	assert j['data']['id'] == userid, resp.text
	assert j['data']['first_name'] == firstname, resp.text

def test_list_invaliduser(supply_url):
	url = supply_url + "/users/50"
	resp = requests.get(url)
	assert resp.status_code == 404, resp.text

Затем файл test_login_user.py содержит тестовые методы для проверки функциональности авторизации.

  • Функция test_login_valid проверяет корректность попытки входа в систему с использованием адреса электронной почты и пароля.
  • Функция test_login_no_password проверяет неверную попытку входа в систему без передачи пароля.
  • Функция test_login_no_email проверяет некорректную попытку входа в систему без передачи адреса электронной почты.
import pytest
import requests
import json
def test_login_valid(supply_url):
	url = supply_url + "/login/" 
	data = {'email':'test@test.com','password':'something'}
	resp = requests.post(url, data=data)
	j = json.loads(resp.text)
	assert resp.status_code == 200, resp.text
	assert j['token'] == "QpwL5tke4Pnpja7X", resp.text

def test_login_no_password(supply_url):
	url = supply_url + "/login/" 
	data = {'email':'test@test.com'}
	resp = requests.post(url, data=data)
	j = json.loads(resp.text)
	assert resp.status_code == 400, resp.text
	assert j['error'] == "Missing password", resp.text

def test_login_no_email(supply_url):
	url = supply_url + "/login/" 
	data = {}
	resp = requests.post(url, data=data)
	j = json.loads(resp.text)
	assert resp.status_code == 400, resp.text
	assert j['error'] == "Missing email or username", resp.text

Запустите тест с помощью команды `py.test -v` и посмотрите результат, который вы увидите ниже.

test_list_user.py::test_list_valid_user[1-George] PASSED                                                                                                                                                                               
test_list_user.py::test_list_valid_user[2-Janet] PASSED                                                                                                                                                                                
test_list_user.py::test_list_invaliduser PASSED                                                                                                                                                                                        
test_login_user.py::test_login_valid PASSED                                                                                                                                                                                            
test_login_user.py::test_login_no_password PASSED                                                                                                                                                                                      
test_login_user.py::test_login_no_email PASSED

Обновите тесты и попробуйте различные варианты результатов.

Часто задаваемые вопросы (FAQ)

Оба запускаются Python Тесты, конечно, существуют, но pytest использует простые операторы assert, требует меньше шаблонного кода и предлагает фикстуры, маркеры и параметризацию. Unittest поставляется со стандартной библиотекой и следует стилю xUnit, основанному на классах. Pytest по-прежнему может запускать существующие тестовые случаи unittest.

Используйте синтаксис идентификатора узла с двойным двоеточием: pytest test_sample1.py::test_file1_method1. Это запустит только один метод. Вы также можете выбрать весь файл (pytest test_sample1.py) или отфильтровать по имени с помощью опции -k.

Установите плагин pytest-cov, затем запустите команду pytest –cov=your_package. Она покажет процент строк, выполненных вашими тестами, а команда –cov-report=html создаст интерактивный отчет, в котором будут выделены непротестированные строки.

Область видимости фикстуры определяет, как часто она выполняется: функция (по умолчанию), класс, модуль, пакет или сессия. Задайте её с помощью `@pytest.fixture(scope=”module”)`. Более широкие области видимости позволяют повторно использовать ресурсоёмкие настройки, такие как подключение к базе данных, во многих тестах.

Запустите pytest -x, чтобы остановить выполнение сразу после первого неудачного теста, или pytest –maxfail=2, чтобы остановить выполнение после выбранного количества неудачных тестов. Это сократит цикл обратной связи при отладке неисправного набора тестов.

Pytest по умолчанию перехватывает стандартный вывод. Добавьте флаг -s (pytest -s), чтобы отключить перехват и отображать сообщения print в режиме реального времени. Флаг -v добавляет подробный вывод для каждого теста, в котором перечисляется имя каждого теста и его результат.

Команды, занимающиеся машинным обучением, используют pytest для проверки конвейеров загрузки данных, преобразований признаков и выходных данных моделей. Фикстуры предоставляют примеры наборов данных, а параметризация проверяет множество входных данных, поэтому интеллектуальные части системы остаются надежными при изменении кода.

Да. GitHub Copilot и агентные ИИ-помощники могут генерировать функции pytest, фикстуры и параметризованные тестовые случаи на основе короткой подсказки или существующей функции. RevПросмотрите сгенерированные утверждения, поскольку ИИ может упускать из виду крайние случаи и неправильно оценивать ожидаемые значения.

Подведем итог этой публикации следующим образом: