程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python automation Excel

編輯:Python

Pytest and Unittest Differences between test frameworks ?

How to distinguish the two , It's simple unittest As an official testing framework , More basic in testing , And it can carry out secondary development on the basis of again , At the same time, the format will be more complex in usage ; and pytest Framework as a third-party framework , The convenience lies in more flexible use , And be able to change the original unittest Style test cases have good compatibility , At the same time, it is richer in expansion , Use scenarios can be added through extended plug-ins , For example, some concurrent tests ;

Pytest install

pip install :

pip install pytest
Copy code 

Test installation successful :

pytest --help
py.test --help
Copy code 

Check the installed version :

pytest --version
Copy code 

Pytest Example

Pytest Writing rules :

  • Test file with test_ start ( With _test For the end )
  • Test the class to Test start ;
  • Test method test_ start
  • Assertions use basic assert

test_example.py

def count_num(a: list) -> int:
return len(a)
def test_count():
assert count_num([1, 2, 3]) != 3
Copy code 

Perform the test :

pytest test_example.py
Copy code 

Execution results :

C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest>pytest test_example.py -v
================================================================= test session starts =================================================================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- d:\coding\python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collected 1 item
test_example.py::test_count FAILED [100%]
====================================================================== FAILURES =======================================================================
_____________________________________________________________________ test_count ______________________________________________________________________
def test_count():
> assert count_num([1, 2, 3]) != 3
E assert 3 != 3
E + where 3 = count_num([1, 2, 3])
test_example.py:11: AssertionError
=============================================================== short test summary info ===============================================================
FAILED test_example.py::test_count - assert 3 != 3
================================================================== 1 failed in 0.16s ==================================================================
Copy code 

remarks :

  • . Means that the test passes ,F Represents a test failure ;
  • -v Displays detailed test information , -h Show pytest Command detailed help ;

Mark

By default ,pytest Will look in the current directory to test_ Start with ( With _test ending ) Test files for , And execute all in the file test_ Start with ( With _test For the end ) All functions and methods of ;

  1. Specify test cases to run , Can pass :: show marks ( file name :: Class name :: Method name )( file name :: Function name )
pytest test_example3.py::test_odd
Copy code 
  1. Specify some test cases and test runs , have access to -k Fuzzy matching
pytest -k example
Copy code 
  1. adopt pytest.mark.skip() perhaps pytest.makr.skipif() Conditional expression , Skip the specified test case
import pytest
test_flag = False
@pytest.mark.skip()
def test_odd():
num = random.randint(0, 100)
assert num % 2 == 1
@pytest.mark.skipif(test_flag is False, reason="test_flag is False")
def test_even():
num = random.randint(0, 1000)
assert num % 2 == 0
Copy code 
  1. adopt pytest.raises() Catch the exceptions that may be thrown by the test case
def test_zero():
num = 0
with pytest.raises(ZeroDivisionError) as e:
num = 1/0
exc_msg = e.value.args[0]
print(exc_msg)
assert num == 0
Copy code 
  1. Know in advance that the test case will fail , But I don't want to skip , Prompt information needs to be displayed , Use pytest.mark.xfail()
@pytest.mark.xfail()
def test_sum():
random_list = [random.randint(0, 100) for x in range(10)]
num = sum(random_list)
assert num < 20
Copy code 
  1. Test multiple groups of data for test cases , Each set of parameters can be executed independently once ( It can avoid executing a single group of data within the test case and stopping the test after failing the test )
@pytest.mark.parametrize('num,num2', [(1,2),(3,4)])
def test_many_odd(num: int, num2: int):
assert num % 2 == 1
assert num2 % 2 == 0
Copy code 

The firmware (Fixture)

Firmware is a preprocessing function ,pytest Before executing the test function ( Or after execution ) Load and run these firmware , Common application scenarios include database connection and closing ( Device connection and shutdown )

Easy to use

import pytest
@pytest.fixture()
def postcode():
return "hello"
def test_count(postcode):
assert postcode == "hello"
Copy code 

According to the official explanation, when running the test function , The parameters of the running function are detected first , Search for parameters with the same name fixture, once pytest find , Will run these firmware , Get the return values of these firmware ( If there is ), And pass these return values as parameters to the test function ;

Pretreatment and post-processing

Next, further verify the official statement :

import pytest
@pytest.fixture()
def connect_db():
print("Connect Database in .......")
yield
print("Close Database out .......")
def read_database(key: str):
p_info = {
"name": "zhangsan",
"address": "China Guangzhou",
"age": 99
}
return p_info[key]
def test_count(connect_db):
assert read_database("name") == "zhangsan"
Copy code 

Execute test function results :

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 1 item
test_example.py::test_count Connect Database in .......
PASSED [100%]Close Database out .......
============================== 1 passed in 0.07s ==============================
Copy code 

remarks :

  • Firstly, the results verify the official explanation ,pytest Before executing the test function, it will look for the firmware with the same name to load and run ;
  • connect_db In firmware yield, here pytest Default will judge yield The code before the keyword belongs to preprocessing , Will be executed before testing ,yield The subsequent code belongs to post-processing , Will be performed after the test ;

Scope

We have a general understanding of the function of firmware from the front , Extract some repetitive work for reuse , meanwhile pytest In order to control firmware more finely in the framework , Scope is used to specify the scope of firmware ,( For example, the first mock exam function in this module can be executed once. , The function in the module does not need to be executed repeatedly ) A more specific example is the database connection , The operation of this connection may be time-consuming , I only need the first mock exam function to run once. , You don't need to run every time .

And defining firmware is , Usually by scop Parameter to declare the action , Commonly used :

  • function: Function level , Each test function will execute the firmware once ;
  • class: Class level , Execute once per test class , All methods can be used ;
  • module: Module level , Each module is executed once , Functions and methods within the module can be used ;
  • session: Session level , A test is executed only once , All the functions and methods found are available .
import pytest
@pytest.fixture(scope="function")
def func_scope():
print("func_scope")
@pytest.fixture(scope="module")
def mod_scope():
print("mod_scope")
@pytest.fixture(scope="session")
def sess_scope():
print("session_scope")
def test_scope(sess_scope, mod_scope, func_scope):
pass
def test_scope2(sess_scope, mod_scope, func_scope):
pass
Copy code 

Execution results :

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items
test_example2.py::test_scope session_scope
mod_scope
func_scope
PASSED [ 50%]
test_example2.py::test_scope2 func_scope
PASSED [100%]
============================== 2 passed in 0.07s ==============================
Copy code 

You can see it here module,session The scope's firmware was executed only once , You can verify the official introduction

Automatic execution

Someone might say , Why is it so troublesome ,unittest Directly defined in the framework setUp Preprocessing can be performed automatically , alike pytest The framework has similar automatic execution ; pytest The firmware in the framework is generally through parameters autouse Control automatic operation .

import pytest
@pytest.fixture(scope='session', autouse=True)
def connect_db():
print("Connect Database in .......")
yield
print("Close Database out .......")
def test1():
print("test1")
def test2():
print("test")
Copy code 

Execution results :

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items
test_example.py::test1 Connect Database in .......
PASSED [ 50%]test1
test_example.py::test2 PASSED [100%]test
Close Database out .......
============================== 2 passed in 0.07s ==============================
Copy code 

It turns out that , The test function is automatically executed before and after running connect_db The firmware ;

A parameterized

I mentioned it briefly earlier @pytest.mark.parametrize Pass parametric test , For firmware parameters, you need to pass pytest Firmware built into the frame request, And through request.param To obtain parameters

import pytest
@pytest.fixture(params=[
('redis', '6379'),
('elasticsearch', '9200')
])
def param(request):
return request.param
@pytest.fixture(autouse=True)
def db(param):
print('\nSucceed to connect %s:%s' % param)
yield
print('\nSucceed to close %s:%s' % param)
def test_api():
assert 1 == 1
Copy code 

Execution results :

============================= test session starts =============================
platform win32 -- Python 3.6.8, pytest-6.2.5, py-1.10.0, pluggy-1.0.0 -- D:\Coding\Python3.6\python.exe
cachedir: .pytest_cache
rootdir: C:\Users\libuliduobuqiuqiu\Desktop\GitProjects\PythonDemo\pytest
plugins: Faker-8.11.0
collecting ... collected 2 items
test_example.py::test_api[param0]
Succeed to connect redis:6379
PASSED [ 50%]
Succeed to close redis:6379
test_example.py::test_api[param1]
Succeed to connect elasticsearch:9200
PASSED [100%]
Succeed to close elasticsearch:9200
============================== 2 passed in 0.07s ==============================
Copy code 

Analog connection here redis and elasticsearch, Load the firmware to automatically perform the connection, then execute the test function and disconnect .

summary

Why should we learn about automated testing for development , It is very important to save some time of repetitive work through automated testing , At the same time, for optimizing the code structure , Improve code coverage , And subsequent project reconstruction are of great significance , At the same time understand pytest and unittest What are the differences on this basis? It is helpful to select suitable test tools in different business scenarios . This article is just a brief introduction pytest Basic use of , If you are interested, please go to the official documents , The use of built-in firmware is also mentioned in the official documents , Common test scenarios, etc .

Reference resources :

docs.pytest.org/en/6.2.x/co…learning-pytest.readthedocs.io/zh/latest/d…


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved