Overview of the article


Fixtures and Unittest conflict. Discard UnitTest and use PyTest only.

There are many use cases where the preconditions look the same. As you write more and more use cases, you’re going to run into the same preconditions, and you’re not that far apart. This way, if every py file has a setUp and tearDown, the repetition rate is pretty high. I wish I could take it out and make it public.

In fact, under unitTest, you can create a public setUpClass, create a separate file, reference it, inherit it, and make it public. You can do it if you want, but PyTest does it better.

Fixtures are used as a common usage in projects. Additional setUp and tearDown can be defined specifically in a separate place, not in the test case. Test cases bring it in as a front and a back.

First of all definefixtureHow do I define that?

It’s a function, but it’s a function, and we’re going to put a little decoration on it, to say that this function has a special purpose. What kind of special use?

It’s our front and back.

The decorator is @pytest.fixture, which precedes the function name.


In PyTest, environment preparation and environment cleanup go together completely. In UnitTest, it’s two separate, one is setUp and one is tearDown, and we’re going to define two functions.

In PyTest, you only need one function. Fixtures can be defined in the current file or in addition.

The first, public:

Prefixes and postfixes are defined in special files that can be called by anyone who wants to use them later. Normally, you need to import functions to call them, but not in PyTest. Just use a decorator to refer to it. You don’t need to reference the file at all.

1. How did it come to be socialized?

In the TeatCase directory, create a New Python file named conftest.


This document is a public document.

conftestThe file must be placed with the test case file, the same level as the test case file.

A fixture is a function.

You can see the source code parsing:


def fixture(
    callable_or_scope=None,
 *args,  scope="function". params=None,  autouse=False,  ids=None,  name=None ):  """Decorator to mark a fixture factory function.   This decorator can be used, with or without parameters, to define a  fixture function.   The name of the fixture function can later be referenced to cause its  invocation ahead of running tests: test  modules or classes can use the ``pytest.mark.usefixtures(fixturename)`` Copy the code

As you can see, the first parameter is scope. Scope is session level, module level, class level, and function level. Represents its scope. The default is function. What is function?

A function is a single test case, that is, each test case. The rest of the parameters can be ignored for now.

The default is function, which stands for setUp and tearDown. Test cases are presented as functions. Since it’s functional, it’s one test case at a time. Class level parameters, source code parsing:

    :arg scope: the scope for which this fixture is shared, one of
` `"function"`` (default), ``"class"` `, ` `"module"` `,` `"package"` `or` `"session"` ` (` `"package"` `is considered **experimental**
                at this time).
Copy the code

The arguments are function, class. Class is set class and tearDownClass.

SetUp and tearDown are applied to each test case, setUpClass and tearDownClass are applied to the test class, and Module is the entire Py file. Package = package; session = session This session refers to the test session. Don’t worry about it if you don’t need it for high level use.

Session-level, which may be useful in interface automation. Each test case may involve database validation, which starts with a database connection, obtaining a database object, and cursor operations. So we can use sessions.

Let’s run this thing before we do any test cases, and then we’ll just use this object for everything else. There is no need to connect in different test cases.

In fact, interface automation can solve this problem with setUpClass.

2. How do you know where it isaccess_webFunction, which code is pre and which code is post?

Use the yield keyword to separate the pre – and post-operations. If no postposition is used, then the yield keyword is left out.

The code is as follows:

import pytest
from selenium import webdriver
from PageObjects.login_page import LoginPage
from TestDatas import Comm_Datas as cd

driver=None  Declare it to be a fixture @pytest.fixture(scope="class") def access_web(a):The entire test class is run only once  global driver  # preloading  print("======= before all test cases are executed, setup==== the entire test class is executed only once ======")  driver=webdriver.Chrome()  driver.get(cd.web_login_url)  lg=LoginPage(driver)  yield(driver,lg) # separator line; # followed by the return value  print("======== after all test cases, teardown==== executes only once ====== for the entire test case")  driver.quit()  # post operation  @pytest.fixture# Defaults to 'setUp' and 'tearDown', so parentheses are not needed here. def refresh_page(a):  global driver  # preloading  yield  # post operation  driver.refresh()  @pytest.fixture(scope="session") def session_demo(a):  print("**** I am the beginning of the entire test session ****")  yield  print("**** I am the end of the entire test session ****")  @pytest.fixture(scope="class") def class_demo(a):  print("**** I am the beginning of class ****")  yield  print("**** I am the end of class ****")   @pytest.fixture def func_demo(a):  print("**** I am the beginning of function ****")  yield  print("**** I am the end of function ****")  Copy the code

Fixture functionality and DDT cannot be shared. DDT is not applicable at this stage. It has its own way of being data-driven.

@pytest.mark.usefixtures(“refresh_page”) can be used in front of the test case, but fixtures are used in every test case of the test class. Everyone does the same thing, so there is no need to do it in front of every function. Just put it in front of the class. We all use it.


@pytest.mark.usefixtures("access_web")# fixtures("access_web"
@pytest.mark.usefixtures("refresh_page")
class TestLogin:

    The name of the function used to receive its return value for the fixture
 @pytest.mark.smoke  def test_login_2_success(self,access_web):The function name of the #fixture is used as the use-case argument to receive the return value from the fixture  logging.info("**** login case: Normal scenario: Use the correct username and password to log in ***")  Step enter your user name and password and click login  access_web[1].login(ld.success_data["user"],ld.success_data["passwd"])  How to find the exit element in the # assertion home page  assert IndexPage(self.access_web[0]).isExist_logout_ele() Copy the code

If you’re logged in, you don’t need it, but setUp and tearDown will do the trick. Because its front and back only for its own use, not for others.

Second, privatization:

What do I do if TestLogin has 9 different prepositions but 1 different prepositions?

This code may run error, usage should be based on the actual code debugging:

@pytest.mark.usefixtures("func_demo")# Executes the access_web function while running
@pytest.mark.usefixtures("class_demo")
@pytest.mark.demo
def test_demo(a):
    print("ffffffffffffffff")
Copy the code

1. Just take the single one out, define it as a function, and put it outside as a function. The other nine are all the same in the class.

2. Suppose that out of 10 test cases, 5 look like this and the other 5 look like this. You can define two test classes. The two test classes use different fixtures.

The above two methods of privatization need practical operation, according to the actual situation to judge the availability and debugging of the two methods.


Welcome to scan code attention!


This article is formatted using MDNICE