Учебное пособие по PyTest: что такое, как установить, фреймворк, утверждения

Что такое PyTest?

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

Зачем использовать PyTest?

Некоторые из преимуществ pytest:

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

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

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

Шаг 1) Вы можете установить pytest с помощью

pip install pytest==2.9.1

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

py.test -h

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

установить PyTest

Первый базовый 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.

F говорит неудача

Точка (.) говорит об успехе.

В разделе сбоев вы можете увидеть неудачные методы и строку сбоя. Здесь x==y означает 5==6, что неверно.

Далее в этом руководстве по PyTest мы узнаем об утверждениях в PyTest.

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

Утверждения Pytest — это проверки, которые возвращают статус True или False. В Python 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 позволяет нам запускать определенные тесты. Мы можем сделать это двумя способами

  • Группировка названий тестов по совпадению подстрок
  • Группировка тестов по маркерам

У нас уже есть 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) Запуск тестов путем сопоставления подстроки

Здесь, чтобы запустить все тесты, имеющие в названии метод 1, нам нужно запустить

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

Вы можете запускать тесты прямо сейчас,

py.test -n 4

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

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

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

Метод помечается как приспособление 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. Этот метод вернет список из трех значений.
  • У нас есть 3 метода тестирования для сравнения каждого значения.

Каждая тестовая функция имеет входной аргумент, имя которого соответствует доступному прибору. Затем 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, а остальные 2 теста не пройдены.

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

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

Давайте посмотрим на это на примере PyTest ниже. Создайте 3 файла 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.parameterize.

Мы увидим это на примере PyTest ниже. Здесь мы передадим 3 аргумента тестовому методу. Этот тестовый метод добавит первые два аргумента и сравнит их с третьим аргументом.

Создайте тестовый файл 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"

Здесь тестовый метод принимает 3 аргумента: вход1, вход2, выход. Он складывает входные данные1 и входные2 и сравнивает их с выходными данными.

Давайте запустим тест с помощью 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

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

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

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

Pytest Xfail / Пропустить тесты

В некоторых ситуациях мы не хотим выполнять тест или прецедент не актуально для конкретного времени. В таких ситуациях у нас есть возможность провалить тест или пропустить тесты.

Тест xfailed будет выполнен, но он не будет засчитан как частично проваленный или пройденный тест. Если этот тест не пройден, обратная трассировка отображаться не будет. Мы можем выполнить тесты xfail, используя

@pytest.mark.xfail.

Пропуск теста означает, что тест не будет выполнен. Мы можем пропустить тесты, используя

@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 (при провале теста) или xpassed (при прохождении теста). Не будет никакого отслеживания ошибок.
  • test_add_5 и test_add_6 будут выполнены, а test_add_6 сообщит об ошибке с помощью обратной трассировки, пока test_add_5 пройдет.

Выполните тест с помощью 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 Framework Тестирование API

Теперь мы создадим небольшую платформу pytest для тестирования API. Используемый здесь API является бесплатным от https://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

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

Резюме

В этом уроке PyTest мы рассмотрели

  • Установите pytest, используя пип установить pytest=2.9.1
  • Простая программа pytest и запустите ее с помощью команды py.test.
  • Операторы утверждения, утверждении x==y, вернут либо True, либо False.
  • Как pytest идентифицирует тестовые файлы и методы.
  • Тестовые файлы, начинающиеся с тестовое задание_ или заканчивая _контрольная работа
  • Методы испытаний, начинающиеся с тест
  • Команда py.test запустит все тестовые файлы в этой папке и подпапках. Чтобы запустить определенный файл, мы можем использовать команду py.test
  • Запустите подмножество методов тестирования
  • Группировка названий тестов по подстроке match.py.test -k -v запустит все тесты, имеющие в его имени.
  • Запустите тест по маркерам. Отметьте тесты с помощью @pytest.mark. и запустите тесты, используя pytest -m для запуска тестов, отмеченных как .
  • Запускайте тесты параллельно
  • Установите pytest-xdist с помощью pip install pytest-xdist
  • Запускайте тесты, используя py.test -n NUM, где NUM — количество рабочих.
  • Создание методов фиксации для запуска кода перед каждым тестом, помечая метод @pytest.fixture.
  • Область действия метода фиксации находится внутри файла, в котором он определен.
  • Доступ к методу фиксации можно получить в нескольких тестовых файлах, определив его в файле conftest.py.
  • Метод тестирования может получить доступ к приспособлению Pytest, используя его в качестве входного аргумента.
  • Параметризация тестов для их запуска на нескольких наборах входных данных.
    @pytest.mark.parameterize("вход1, ввод2, вывод",[(5,5,10),(3,5,12)])
    def test_add(вход1, ввод2, вывод):
    утверждать ввод1+ввод2 == вывод «не удалось»
    запустит тест с входными данными (5,5,10) и (3,5,12)
  • Пропустить тесты/xfail, используя @pytets.mark.skip и @pytest.mark.xfail.
  • Создайте результаты теста в формате XML, который охватывает детали выполненного теста, используя py.test test_sample1.py -v –junitxml=”result.xml”
  • Пример фреймворка pytest для тестирования API