SoFunction
Updated on 2024-10-28

Pytest framework of fixture detailed use of tutorials

preamble

In the previous article, we talked about how setup and teardown can be used to add some operations before or after the execution of a use case, but this is a global effect for the entire script.
If you have the following scenario: use case 1 requires login, use case 2 does not require login, and use case 3 requires login. Obviously this can't be done with setup and teardown. fixture allows us to customize the preconditions of our test cases.

The fixture advantage

  • Naming is flexible, not limited to setup and teardown.
  • Data sharing can be implemented in the configuration so that fixtures can be found automatically without the need for import.
  • scope="module" enables multiple .py frontends to be shared across files.
  • scope="session" to enable multiple .py cross-files to use one session for multiple use cases

List of fixture parameters

@(scope="function", params=None, autouse=False, ids=None, name=None)
def test():
print("List of parameters for fixture initialization")

parameter list

  • scope: can be interpreted as the scope of the fixture, default: function, and class, module, package, session four [common]
  • autouse: Default: False, the fixture needs to be called manually by the use case; if it is True, the fixture will be called automatically by all the test cases in the scope.
  • name: default: the name of the decorator, it is recommended that fixtures of the same module call each other with a different name.

take note of

Scope of session: the entire test session, i.e., from the start of pytest execution to the end of the test.

How test cases call fixture

  • Use the name of the fixture as an input parameter to the test case function
  • Test case plus decorator: @(fixture_name)
  • fixture set autouse=True
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ =
__Time__ = 2020-04-06 15:50
__Author__ = Pineapple Test Notes
__Blog__ = /poloyy/
"""
import pytest
# Call mode one
@
def login():
 print("Enter your account number and password to log in first.")

def test_s1(login):
 print("Use Case 1: Other actions after login 111")

def test_s2(): # Don't pass login
 print("Use case 2: no login required, operation 222")

# Call mode two
@
def login2():
 print("PLEASE enter your account number and password to log in first.")

@("login2", "login")
def test_s11():
 print("Use Case 11: Other Actions After Login 111")

# Calling style three
@(autouse=True)
def login3():
 print("====auto===")

# If it doesn't start with test, the decorator won't execute the fixture.
@("login2")
def loginss():
 print(123)

Implementation results

Instantiation order of fixture

  • Higher scope fixtures (sessions) are instantiated before lower scope fixtures (functions, classes) [session > package > module > class > function].
  • Fixtures with the same scope follow the order in which they are declared in the test function and follow the dependencies between fixtures [fixture_B, which is dependent inside fixture_A, is instantiated first, and then goes to fixture_A for instantiation].
  • A fixture that is used automatically (autouse=True) will be instantiated before a fixture that is used explicitly (passing a parameter or decorator)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
__title__ =
__Time__ = 2020-04-06 16:14
__Author__ = Pineapple Test Notes
__Blog__ = /poloyy/
"""
import pytest
order = []
@(scope="session")
def s1():
 ("s1")
@(scope="module")
def m1():
 ("m1")
@
def f1(f3, a1):
 # Instantiate f3, then a1, then f1.
 ("f1")
 assert f3 == 123
@
def f3():
 ("f3")
 a = 123
 yield a
@
def a1():
 ("a1")
@
def f2():
 ("f2")
def test_order(f1, m1, f2, s1):
 # m1, s1 after f1, but will be instantiated first because of the large scope of the scope
 assert order == ["s1", "m1", "f3", "a1", "f1", "f2"]

Implementation results

Assertion of success

A note about fixtures

Added@ If the fixture also wants to depend on other fixtures, it needs to be passed as a function, not a@() way, otherwise it will not take effect

@(scope="session")
def open():
 print("===Open your browser.===")

@
# @("open") Not desirable!!!! Not valid!!!
def login(open):
 # method-level preemptive operation setup
 print(f"Enter account number,Password to log in first{open}")

The previous, in fact, are setup operations, so now let's talk about teardown is how to realize the

Implementing teardown with fixture is not a standalone function, but uses the yield keyword to turn on the teardown operation

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
__title__ =
__Time__ = 2020-04-06 15:50
__Author__ = Pineapple Test Notes
__Blog__ = /poloyy/
"""

import pytest

@(scope="session")
def open():
 # Session preemptive operation setup
 print("===Open your browser.===")
 test = "Tests whether a variable returns"
 yield test
 # Session post operation teardown
 print("==Close Browser==")

@
def login(open):
 # method-level preemptive operation setup
 print(f"Enter account number,Password to log in first{open}")
 name = "==I'm the account number.=="
 pwd = "==I'm the password.=="
 age = "==I'm of age.=="
 # Return variables
 yield name, pwd, age
 # method level post operation teardown
 print("Login successful.")

def test_s1(login):
 print("==use case1==")
 # Returns a tuple
 print(login)
 # Assigned to separate variables
 name, pwd, age = login
 print(name, pwd, age)
 assert "Account number." in name
 assert "Password." in pwd
 assert "Age" in age

def test_s2(login):
 print("==use case2==")
 print(login)

Field Notes

  • If the code before the field, i.e., the setup part, has already thrown an exception, the teardown after the field will not be executed.
  • If the test case throws an exception, the contents of the teardown after the yield will still be executed normally

Combination of yield+with

# Official examples
@(scope="module")
def smtp_connection():
 with ("", 587, timeout=5) as smtp_connection:
 yield smtp_connection # provide the fixture value

ought to smtp_connection The connection will be tested to finish execution after it has been closed because thesmtp_connection When the object is automatically closed, the with End of statement.

addfinalizer terminator function

@(scope="module")
def test_addfinalizer(request):
 # Pre-operation setup
 print("==Open the browser again==")
 test = "test_addfinalizer"

 def fin():
 # Post-operation teardown
 print("==Close the browser again==")

 (fin)
 # Return the variables of the preceding operation
 return test
def test_anthor(test_addfinalizer):
 print("==Latest Use Cases==", test_addfinalizer)

 caveat

If the code before (), i.e. the setup part, already throws an exception, the teardown content of () will not be executed (similar to yield, I think it's been changed to be consistent in newer versions recently)
Multiple terminating functions can be declared and called

summarize

to this article on the Pytest framework of fixture detailed tutorials on the use of the article is introduced to this, more related to the use of Pytest fixture content, please search for my previous articles or continue to browse the following related articles I hope that you will support me in the future more!