pytest笔记

1.cmd中

pip install pytest
#安装
 pytest --version
#查看版本

创建test_samplle.py放在桌面,内容为

# content of test_sample.py
def func(x):
    return x + 1


def test_answer():
    assert func(3) == 5

运行test_samplle.py

cd C:\Users\LDP\Desktop
pytest test_sample.py


image
image

在桌面新建test_pytest01.py 文件,内容为

def test_one():
    print("开始执行 test_one 方法")
    x = 'this'
    assert 'h' in x

def test_two():
    print("开始执行 test_two 方法")
    x = 'may'
    assert 'm' in x

def test_three():
    print("开始执行 test_three 方法")
    x = 'this'
    assert 'y' in x
pytest test_pytest01.py

pytest -v test_pytest01.py

pytest -s test_pytest01.py
#所有print打印的信息都可以打印到终端上


只打算执行一个文件中的某个类:
桌面新建文件 test_pytest02.py

class TestDemo1():
    # 类名要以Test开始
    def test_one(self):
        print("开始执行 test_one 方法")
        x = 'this'
        assert 'h' in x

    def test_two(self):
        print("开始执行 test_two 方法")
        x = 'may'
        assert 'm' in x

    def test_three(self):
        print("开始执行 test_three 方法")
        x = 'this'
        assert 'y' in x


class TestDemo2():

    def test_demo_one(self):
        print("开始执行 test_demo_one 方法")
        x = 'this'
        assert 'h' in x

    def test_demo_two(self):
        print("开始执行 test_demo_two 方法")
        x = 'may'
        assert 'm' in x

    def test_demo_three(self):
        print("开始执行 test_demo_three 方法")
        x = 'this'
        assert 'y' in x

pytest test_pytest02.py::TestDemo1


想执行类中的某一个方法

pytest test_pytest02.py::TestDemo1::test_two


想跳过某个方法

pytest test_pytest02.py -k "TestDemo1 and not test_two"


一旦运行报错就立刻停止

pytest test_pytest02.py -x


当运行错误达到某个值就停止

pytest test_pytest02.py --maxfail=1
#错误达到1就停止


当用例错误的时候重新运行
安装
pip install pytest_rerunfailures

pytest --reruns 3 test_pytest02.py
#当用例失败的时候重复执行三次


每次重新执行等待几秒

pytest --reruns 3 --reruns-delay 2 test_pytest02.py
#每次rerun 延迟2秒

image
在test_pytest02.py 中加断言

import pytest
import pytest_assume
class TestDemo1():
    def test_one(self):
        print("开始执行 test_one 方法")
        x = 'this'
        # assert 'h' in x
        pytest.assume('h' not in x)
        pytest.assume(1 == 2)
        pytest.assume('x' in 'xxx')

    def test_two(self):
        print("开始执行 test_two 方法")
        x = 'may'
        assert 'm' in x

    def test_three(self):
        print("开始执行 test_three 方法")
        x = 'this'
        assert 'y' in x


class TestDemo2():
    def test_demo_one(self):
        print("开始执行 test_demo_one 方法")
        x = 'this'
        assert 'h' in x

    def test_demo_two(self):
        print("开始执行 test_demo_two 方法")
        x = 'may'
        assert 'm' in x

    def test_demo_three(self):
        print("开始执行 test_demo_three 方法")
        x = 'this'
        assert 'y' in x

  1. 在pycharm中
import pytest
import pytest_assume
class TestDemo1():
    # 类名要以Test开始
    def test_one(self):
        print("开始执行 test_one 方法")
        x = 'this'
        # assert 'h' in x
        pytest.assume('h' not in x)
        pytest.assume(1 == 2)
        pytest.assume('x' in 'xxx')

    def test_two(self):
        print("开始执行 test_two 方法")
        x = 'may'
        assert 'm' in x

    def test_three(self):
        print("开始执行 test_three 方法")
        x = 'this'
        assert 'y' in x


class TestDemo2():
    def test_demo_one(self):
        print("开始执行 test_demo_one 方法")
        x = 'this'
        assert 'h' in x

    def test_demo_two(self):
        print("开始执行 test_demo_two 方法")
        x = 'may'
        assert 'm' in x

    def test_demo_three(self):
        print("开始执行 test_demo_three 方法")
        x = 'this'
        assert 'y' in x

if __name__ == '__main__':
#执行模块里的所有用例
    pytest.main()
# 执行模块里的所有用例
    # pytest.main("-v -x TestDemo1")
    # 另一种写法
    #pytest.main(['-v', '-x', 'TestDemo2'])

注意设置


image
image

import pytest


@pytest.fixture()
def login():
    print("这是一个登录方法")


def test_case1(login):
    print("开始执行 test_one 方法要登录")
    pass


def test_case2():
    print("开始执行 test_two 方法,不用登录")
    pass


def test_case3(login):
    print("开始执行 test_three 方法,要登录")
    pass


if __name__ == '__main__':
    pytest.main()

当测试的前提条件不同的时候可以用这种方法
image
公共的代码块可以放入
conftest.py


列如在conftest.py写入

import pytest
@pytest.fixture
def login():
    print("这是一个登录方法")

在另一个文件中用

import pytest


def test_case1(login):
    print("开始执行 test_one 方法要登录")
    pass


def test_case2():
    print("开始执行 test_two 方法,不用登录")
    pass


def test_case3(login):
    print("开始执行 test_three 方法,要登录")
    pass


if __name__ == '__main__':
    pytest.main()

yied使用

import pytest


# 作用域,module是在模块之前执行,模块之后执行
@pytest.fixture(scope="module")
def open():
    print("打开浏览器")
    #yield
    print("执行teardown")
    print("关闭浏览器")


def test_search1(open):
    print("test_search1")
    raise NameError
    pass


def test_search2(open):
    print("test_search2")
    pass


def test_search3(open):
    print("test_search3")
    pass


if __name__ == '__main__':
    pytest.main()

import pytest


# 作用域,module是在模块之前执行,模块之后执行
@pytest.fixture(autouse=True)
#下面的每个test都会执行open,打印出打开浏览器
def open():
    print("打开浏览器")


def test_search1():
    print("test_search1")
    pass


def test_search2():
    print("test_search2")
    pass


def test_search3():
    print("test_search3")
    pass


if __name__ == '__main__':
    pytest.main()

image

import pytest
import sys


# 参数化前两个变量,后面是对应的数据
# 3+5——>input.8——>expect
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+5", 7), ("7*5", 30)])
def test_eval(test_input, expected):
    # eval将字符串str当初有效的表达式来求值,并返回结果
    assert eval(test_input) == expected

将方法作为参数传入

import pytest
import sys

'''
# 参数化前两个变量,后面是对应的数据
# 3+5——>input.8——>expect
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+5", 7), ("7*5", 30)])
def test_eval(test_input, expected):
    # eval将字符串str当初有效的表达式来求值,并返回结果
    assert eval(test_input) == expected

'''
test_user_data = ['Tom', 'Jerry']


@pytest.fixture(scope="module")
def login_r(request):
    # 这是接收并传过来的参数
    user = request.param
    print(f"\n 打开首页准备登陆,登录用户:{user}")
    return user


# indirect=True ,可以吧传过来的参数当函数来执行
@pytest.mark.parametrize("login_r", test_user_data, indirect=True)
def test_login(login_r):
    a = login_r
    print(f"测试中的login返回值; {a}")
    assert a != ""

pytest.mark.skip
跳过

import pytest
import sys


# 参数化前两个变量,后面是对应的数据
# 3+5——>input.8——>expect
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+5", 7), ("7*5", 30)])
def test_eval(test_input, expected):
    # eval将字符串str当初有效的表达式来求值,并返回结果
    assert eval(test_input) == expected


test_user_data = ['Tom', 'Jerry']


@pytest.fixture(scope="module")
def login_r(request):
    # 这是接收并传过来的参数
    user = request.param
    print(f"\n 打开首页准备登陆,登录用户:{user}")
    return user

@pytest.mark.skip("这次不执行登录")
#跳过也可以加条件
#pytest.mark.skip(sys.platform == "darwin",reason="不在mac上执行")
# indirect=True ,可以吧传过来的参数当函数来执行
@pytest.mark.parametrize("login_r", test_user_data, indirect=True)
def test_login(login_r):
    a = login_r
    print(f"测试中的login返回值; {a}")
    assert a != ""
if __name__ == '__main__':
    pytest.main()

pytest.mark.xfail
标注测试用例中想跳过的,比如预计会失败,它并不是真的fail了

import pytest


@pytest.mark.search
def test_search1():
    print("test_search1")
    raise NameError
    pass

@pytest.mark.search
def test_search2():
    print("test_search2")
    pass

@pytest.mark.search
def test_search3():
    print("test_search3")
    pass
@pytest.mark.login
def test_login1():
    print("test_login1")
    pass
@pytest.mark.login
def test_login2():
    print("test_login2")
    pass
if __name__ == '__main__':
    pytest.main()
    #全部执行

在pycharm的terminal中执行

pytest -v test_mark_search.py -m login



只有标记为login的才执行,但是这儿报了warning

解决方法在conftest.py 中加下面的内容

def pytest_configure(config):
    marker_list = ["search","login"]
    for markers in marker_list:
        config.addinivalue_line("markers",markers)

就不会再报warning


pytest -v -s --html=report.html --self-contained-
html

关闭