Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> Python

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

Что такое PyTest?

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

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

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

Из этого руководства по Python PyTest вы узнаете:

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

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

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

pip install pytest==2.9.1

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

py.test -h

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

Первый базовый PyTest

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

Создайте папку Study_pytest. Мы собираемся создать наши тестовые файлы в этой папке.

Перейдите к этой папке в командной строке.

Создайте файл с именем test_sample1.py внутри папки

Добавьте в него приведенный ниже код и сохраните

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

Здесь, в test_sample1.py F.

F говорит об ошибке

Точка(.) означает успех.

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

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

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

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

Примеры Pytest Assert:

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:test failed x=5 y=6

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

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

Посмотрите несколько примеров допустимых и недопустимых имен файлов 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) Запуск тестов путем сопоставления подстрок

Здесь, чтобы запустить все тесты, имеющие в своем имени 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

Теперь вы можете запускать тесты,

py.test -n 4

-n <число> запускает тесты с использованием нескольких рабочих процессов. В приведенной выше команде будет 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"

Здесь

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

Мы увидим это на приведенном ниже примере 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 аргумента:input1, input2, output. Он добавляет input1 и input2 и сравнивает с выводом.

Запустим тест 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 / Пропустить тесты

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

Тест 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"

Здесь

Выполните тест с помощью 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 будет записан результат выполнения теста. Найдите образец результата.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 — содержит тестовые методы для вывода действительных и недействительных пользователей

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 — содержит методы тестирования для проверки функциональности входа в систему.

import pytest
import requests
import json
def test_login_valid(supply_url):
	url = supply_url + "/login/" 
	data = {'email':'[email protected]','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':'[email protected]'}
	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 мы рассмотрели


Python

  1. Как установить WordPress в Google Cloud
  2. Учебное пособие по платформе автоматизации тестирования закодированного пользовательского интерфейса
  3. Что такое ключ безопасности сети? Как его найти?
  4. Что такое звонки по WiFi? Как это работает?
  5. Что такое 6G и насколько быстро он будет?
  6. Как установить выравниватель док-станции
  7. Тестирование частичного разряда:что это такое и как оно работает
  8. Что такое кавитация насоса и как ее избежать?
  9. Что такое медная пайка и как это сделать?
  10. Что такое невыполненная работа по обслуживанию? Как это преодолеть?