Tep is a testing tool that integrates a third-party package based on the PyTest testing framework and provides project scaffolding to help quickly implement automatic project implementation by writing Python code.

In the TEP project, automated test cases are stored in the tests directory, and each. Py file is independent of each other. One file means one use case, separated from each other.

Although use cases can also refer to each other, but unless absolutely necessary, it is generally not recommended to do so, dragging the whole body, difficult to maintain later.

Use case coding, thinking from the top down, and pyTest/UnitTest/Script writing is the same, there is no learning cost, generally no problem. Fixtures (a measure of fixtures), tep environment variables (a measure of fixtures), and use cases (a measure of fixtures) are fixtures (a measure of fixtures). In order to more flexible with tep to achieve pyTest automation project.

Suppose we did not use environment variables and fixtures

A: We are fixtures! For example, create a new script login_test.py under tests:

from tep.client import request

def test() :
    response = request("post",
            url="https://qa.com/api/users/login",
            headers={"Content-Type": "application/json"},
            json={
                "username": "admin"."password": "123456",})assert response.status_code < 400
Copy the code

Request interface https://qa.com/api/users/login, asserts that the response status code is less than 400. The url is fixed. What if you need to switch between qa and Release?

A parameterized

Whether you’re doing automated testing or performance testing, you’ll come across the term parameterization. It refers to defining fixed data (hard-coded) in code as variables so that each run time data is different and fixed data becomes dynamic data. Sources of dynamic data are variables, databases, external files, and so on. Dynamic data is typically a string of constants and can be functions, such as JMeter’s function assistant, or dependency injection, such as PyTest’s fixture.

Dependency injection fixtures

Dependency injection is an IoC (Inversion of Control) technology. This is an Inversion of Control technology.

This means that given the client an Injector, the client doesn’t need to do anything to use the service.

Pytest’s fixtures implement dependency injection, allowing us to introduce fixtures to add something extra without changing the test code.

For urls, domain names need to be parameterized in different environments, so TEP has made its fixture through function parameters:

from tep.client import request
from tep.fixture import *

def test(url) :  # into fixture
    response = request("post",
            url=url("/api/users/login"),
            headers={"Content-Type": "application/json"},
            json={
                "username": "admin"."password": "123456",})assert response.status_code < 400
Copy the code

Tep.fixture. Url is defined as follows:

@pytest.fixture(scope="session")
def url(env_vars) :
    def domain_and_uri(uri) :
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain + uri

    return domain_and_uri
Copy the code

If you get it at a glance, congratulations. If you get confused at a glance, it doesn’t matter. I’ll try to get it across. It’s crucial!

Think of fixtures as variables

While fixtures are, by definition, functions defined using the def keyword, they should be understood as variables. Such as:

import pytest


@pytest.fixture
def name() :
    return "dongfanger"
Copy the code

The usual use of a function is the name of the function followed by parentheses, with the name() to get “dongfanger”. Fixtures are different. The above definition can be interpreted as:

name = "dongfanger"
Copy the code

Assign “dongfanger” to name, and the fixture name = return value. You get “dongfanger” from the variable name.

Since it is a variable, it can be assigned to anything: STR, function, class, object. For example, define a function inside a fixture:

import pytest


@pytest.fixture
def who() :
    def get_name() :
        return "dongfanger"
    return get_name
Copy the code

Assign the function name get_name to the fixture name variable:

who = get_name
Copy the code

Get_name is the function name. Get_name () is parentheses to get “dongfanger”. Who must also pass who() to get “dongfanger”. Tep.fixture. Url: tep.fixture. Url

@pytest.fixture(scope="session")
def url(env_vars) :
    def domain_and_uri(uri) :
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain + uri

    return domain_and_uri
Copy the code

Assign the function name domain_and_uri to the fixture name variable:

url = domain_and_uri
Copy the code

Use url(“/ API “) to obtain the concatenated result of the domain name and URI.

Def URL (env_vars) on line 2: also has a parameter env_vars, explained next.

Fixture parameters are other fixtures

The arguments to a fixture can only be other fixtures. Such as:

import pytest


@pytest.fixture
def chinese_name() :
    return "Er" in the east


@pytest.fixture
def english_name(chinese_name) :
    return "dongfanger"
Copy the code

When pyTest calls english_name, it executes its own english_name after executing the other fixture chinese_name in the argument.

Tep.fixture. Url is clear if you break it down into two steps. Step 1:

@pytest.fixture(scope="session")
def url(env_vars) :
    func = None
    return func
Copy the code

The second step:

@pytest.fixture(scope="session")
def url(env_vars) :
    func = None
    
    
    def domain_and_uri(uri) :
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain + uri

    
    func = domain_and_uri
    return func
Copy the code

The environment variable

The tep.fixture. Url argument is another fixture env_vars environment variable, defined as follows:

from tep.fixture import *


@pytest.fixture(scope="session")
def env_vars(config) :
    class Clazz(TepVars) :
        env = config["env"]

        """Variables define start"""
        # Environment and variables
        mapping = {
            "qa": {
                "domain": "https://qa.com",},"release": {
                "domain": "https://release.com",}# Add your environment and variables
        }
        # Define properties for auto display
        domain = mapping[env]["domain"]
        """Variables define end"""

    return Clazz()

Copy the code

Just look at the middle notes “”Variables define start”” to “”Variables define end””. The url parameterized domain name is here. The Mapping dictionary establishes the mapping between environment and variables, and obtains different variable values according to different environment keys.

The config fixture reads the configuration in the conf.yaml file.

Tep’s fixture env_vars draws on JMeter’s user-defined variables:

Env_vars.put () and env_vars.get() borrow from the JMeter BeanShell vars.put() and vars.get().

Example: Test multiple urls

A: We are fixtures (a measure of quality) in the use of the environment variable. If the QA environment has two web sites, the school side and the institution side, the script will be used.

Step 1 Modify env_vars by editing fixture_env_vars.py:

        """Variables define start"""
        # Environment and variables
        mapping = {
            "qa": {
                "domain": "https://qa.com"."domain_school": "https://school.qa.com".# new
                "domain_org": "https://org.qa.com"  # new
            },
            "release": {
                "domain": "https://release.com"."domain_school": "https://school.release.com"  # new
                "domain_org": "https://org.release.com"  # new
            }
            # Add your environment and variables
        }
        # Define properties for auto display
        domain = mapping[env]["domain"]
        domain_school = mapping[env]["domain_school"]  # new
        domain_org = mapping[env]["domain_org"]  # new
        """Variables define end"""
Copy the code

Six lines of code were added to define env_vars.domain_school and env_vars.domain_org.

Fixtures: used to specify fixture_url.

@pytest.fixture(scope="session")
def url_school(env_vars) :
    def domain_and_uri(uri) :
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain_school + uri

    return domain_and_uri
    

@pytest.fixture(scope="session")
def url_org(env_vars) :
    def domain_and_uri(uri) :
        if not uri.startswith("/"):
            uri = "/" + uri
        return env_vars.domain_org + uri

    return domain_and_uri
Copy the code

See TEp.fixture. Url to change env_vars.domain to env_vars.domain_school and env_vars.domain_org, and add two fixtures url_school and url_org.

Going a step further, you might define fixtures login_school and login_org, with some flexibility.

summary

Fixtures and use cases (teP.fixture. Url) : fixtures and use cases (teP.fixture. Url) Fixtures limit the need to use fixtures because, by default, you can’t pass arguments to a function that someone else has written, and you need to reuse the return values. Some of you have a habit of defining function arguments that don’t change. While you can define internal functions for parameter passing, this is not recommended, and it is better to add redundant code and define multiple fixtures than to have code that is well coupled. Fixtures fixtures in ConfTest. py: pyTest fixtures fixtures in Conftest. py: PYtest fixtures fixtures in Conftest. py: CONFtest. py Avoid the possible looping import problem.