专栏/超级详细的pytest测试和allure测试报告

超级详细的pytest测试和allure测试报告

2022年11月20日 11:20--浏览 · --点赞 · --评论
粉丝:58文章:1

1、pytest可以识别执行的测试文件包括

test_*.py

*_test.py

都可以识别该文件

测试用例识别:Test*类包含的所有test_*的方法(测试类不能带有__init__方法);不在class中的所有的test_*方法都可以识别

2、安装直接使用pip install -U pytest命令安装即可 

3、pytest -k以指定匹配运行某个测试测试用例,后面再加上-v可以查看某个测试用例的详细执行结果

pytest --collect-only 只收集测试用例

pytest -m mark 标签名 标记

我们看到有一个warning,产生的原因是这些标签不是可以识别的,那么我们怎么处理这个warning呢,我们可以创建一个pytest.ini文件进行注册这个标签,**自定义标签名**,内容如下

[pytest]

markers = case1

我们再次运行试下发现warning没有了

pytest.ini配置文件是pytest的主配置文件,一般放在项目工程的根目录,它可以指定pytest的运行方式,并且不能使用任何的中文符号

测试用例模块test_a.py:


```python

class Test_A():


    def test_case_a(self):

        print(f"测试用例A")

        assert 6 > 5


    def test_case_b(self):

        print(f"测试用例B")

        assert 9 > 7

```

测试用例模块check_b.py:


```python

class Check_B():


    def aaa_case_a(self):

        print(f"测试用例A---")

        assert 6 > 5


    def aaa_case_b(self):

        print(f"测试用例B---")

        assert 9 > 7

```

**我们新建一个pytest.ini文件,来指定运行check开头的测试用例和模块**

[pytest]

python_files = check_*

python_classes = Check_*

python_functions = aaa_*

运行pytest -v -s

可以看出只收集到了两条测试用例,分别是check_b.py模块下的两条测试用例,符合我们的预期

**因为在执行pytest的时候,会首先执行我们的配置文件pytest.ini文件,所以我们可以在配置文件里面配置我们想要运行的命令,假设我们增加addopts = -v -s --alluredir=./result,如下**

我们直接运行pytest

**我们也可以忽略某些文件夹,使用norecursedirs =**  运行时忽略某些文件夹,后面写上要忽略的文件夹名称

pytest框架结构

模块级别(setup_module/teardown_module)全局的

函数级别(setup_function/teardown_function)只对函数用例生效,**在类外面**

类级(setup_class/teardown_class)只在类中前后运行一次

方法级(setup_method/teardown_method)开始于方法始末,**在类里面**

类里面的(setup/teardown)运行在调用方法的前后


## 4、参数化

使用@pytest.mark.parametrize进行参数化

@pytest.mark.parametrize(argnames, argvalues)

argnames:要参数化的变量,string(逗号分隔),list,tuple

argvalues:参数化的值, list,list[tuple]


```python

import pytest


def inc(x):

    return x + 1


@pytest.mark.parametrize('a,b',[(1,2),(5,6),(7,8),(9,10)])

def test_answer_01(a,b):

    assert inc(a) == b

```

运行结果:

yaml实现参数化

yaml实现list


```python

list

- 10

- 20

- 30

```

yaml实现字典


```python

dict

by:id

locator:name

action:click

```

yaml进行嵌套一

```python

-

- by:id

- locator:name

- action:click

```

yaml进行嵌套二

```python

companies:

-

id:1

name:lili

age:16

-

id:2

name:youyou

age:18

```

我们先安装yaml这个库

使用如下进行加载yaml内容


```python

import pytest

import yaml


def inc(x):

    return x + 1


@pytest.mark.parametrize(("a","b"),yaml.safe_load(open("./data.yaml")))

def test_answer_01(a,b):

    assert inc(a) == b

```

数据文件:

```python

-

  - 1

  - 2

-

  - 3

  - 4

-

  - 6

  - 7

-

  - 10

  - 11

```

运行结果:


## 5、场景一:假设测试用例在执行前需要登陆,那么我们可以在执行前调用登录的方法,前提是要定义一个登陆方法,并且使用fixture进行装饰,同时,在测试用例中,也能够接收登陆函数的返回


```python

@pytest.fixture()

def login():

    print("要开始登陆了哈")

    username = "xiongda"

    return username


class Test_A:


    def test_answer_02(self,login):

        print(f"test_answer_02  login={login}")


if __name__ == '__main__':

    pytest.main()

```

运行结果:


## 场景二:在与其他测试工程师一起合作的时候,公共的模块要在不同的文件中 可以使用conftest.py这个文件进行数据共享,它放在不同位置起着不同范围的共享作用;当前conftest这个文件的文件名是不能变化的。

conftest.py的作用域是:对当前同级目录下所有的文件及包下的所有测试文件,测试方法生效,如果同级目录下没有conftest.py,会找上级目录或者上上级目录 的conftest.py里的fixture方法。

我们新建一个conftest.py文件

内容如下:


```python

import pytest


@pytest.fixture()

def login():

    print("这个是公共的方法")

    return "公共方法"

```

test_a.py文件内容


```python

class Test_A():


    def test_case01(self,login):

        print(f"测试用例1 {login}")


    def test_case02(self):

        print("测试用例2")


    def test_case03(self):

        print("测试用例3")


    def test_case04(self):

        print("测试用例4")

```

我们运行test_case01这个测试用例,发现也能运行成功


## 场景三:我们可以使用scope来控制setup和teardown的作用域和范围


修改conftest.py文件如下


```python

import pytest


@pytest.fixture(scope = "class")

def login():

    print("这个是公共的方法")

    yield "公共方法"  #yield激活fixture  teardown方法

    print("teardown")

```

运行整个test_a.py这个模块

注意:scope = "session"表示在整个目录中只执行一次

scope = "moudle"表示每一个模块也就是每个.py文件执行一次


## 场景四:不想让原有的测试方法有所改动,想让每一个测试用例都运行公共的方法,我们可以使用autouse


修改condtest.py文件如下:@pytest.fixture(autouse=True)


```python

import pytest


@pytest.fixture(autouse=True)

def login():

    print("这个是公共的方法")

    yield "公共方法"  #yield激活fixture  teardown方法

    print("teardown")

```


```python

class Test_A():


    def test_case01(self, login):

        print(f"测试用例1 {login}")


    def test_case02(self):

        print(f"测试用例2")


    def test_case03(self):

        print(f"测试用例3")


    def test_case04(self):

        print("测试用例4")

```

我们可以看到每一个测试用例都用到了公共的方法


## 场景五:为了使数据更加灵活,一般数据都是通过参数进行传递的,我们可以通过fixture固定参数request传递

修改conftest.如下

```python

import pytest

@pytest.fixture(autouse=True, params=["user1", "user2", "user3"])

def login(request):

    print("这个是公共的方法")

    print(request.param)

    yield ["user", "name"]  #yield激活fixture  teardown方法

    print("teardown")

```


```python

class Test_A():


    def test_case01(self):

        print(f"测试用例1")


    def test_case02(self):

        print(f"测试用例2")


    def test_case03(self):

        print(f"测试用例3")


    def test_case04(self):

        print("测试用例4")

```

运行结果:

我们可以看到每一个测试用例下面都使用了这几个参数,和参数化功能相差不多


## 场景六:fixture与参数化相结合,传入一个fixture方法,将数据传入到fixture方法中,fixture方法使用request参数来接收这组数据


conftest.py:


```python

import pytest


@pytest.fixture()

def login(request):

    print("这个是公共的方法")

```

test_a.py


```python

import pytest


class Test_A():


    @pytest.mark.parametrize("login", [(1, 1), (3, 3), (5, 5)], indirect = True)

    def test_case01(self, login):

        print(f"测试用例1")

```

运行结果:

## pytest实用的插件介绍

## **pip install pytest-ordering 控制用例的执行顺序**

pytest的默认执行顺序是自上向下执行(注意pytest多个装饰器的时候可能会发生冲突),如果要调整顺序,我们可以使用@pytest.mark.run(order=1),如果不小心标记成了相同的顺序,测试用例就按照自上而下执行了

代码如下:


```python

import pytest


class Test_A():


    @pytest.mark.run(order=3)

    def test_case01(self):

        print(f"测试用例1")

        assert 2 > 1


    @pytest.mark.run(order=2)

    def test_case02(self):

        print(f"测试用例2")

        assert 2 > 0


    @pytest.mark.run(order=1)

    def test_case03(self):

        print(f"测试用例3")

        assert 28 > 12

```

运行结果:


## pip install pytest-dependency 控制用例的依赖关系

@pytest.mark.dependency(depends=[依赖的测试用例名称])

比如说测试用例C对测试用例A和测试用例B都有依赖关系,我们希望只有当测试用例A和测试用例B都执行通过后,才去执行C,否则跳过C

假设测试用例D也依赖与测试用例A

当测试用例A失败的时候,测试用例C和测试用例D都会直接跳过,如下:


```python

import pytest


class Test_A():


    @pytest.mark.dependency()

    def test_case_a(self):

        print(f"测试用例A")

        assert 2 > 5


    @pytest.mark.dependency()

    def test_case_b(self):

        print(f"测试用例B")

        assert 2 > 0

    @pytest.mark.dependency(depends=['test_case_a', 'test_case_b'])

    def test_case_c(self):

        print(f"测试用例C")

        assert 28 > 12


    @pytest.mark.dependency(depends=['test_case_a'])

    def test_case_d(self):

        print(f"测试用例D")

        assert 28 > 12


    def test_case_e(self):

        print(f"测试用例E")

        assert 28 > 12

```

运行结果如下:

当测试用例A运行通过,测试用例B运行不通过的时候,测试用例C运行不会通过,测试用例D和测试用例E运行通过,如下:


```python

import pytest


class Test_A():


    @pytest.mark.dependency()

    def test_case_a(self):

        print(f"测试用例A")

        assert 6 > 5


    @pytest.mark.dependency()

    def test_case_b(self):

        print(f"测试用例B")

        assert 2 > 7

    @pytest.mark.dependency(depends=['test_case_a', 'test_case_b'])

    def test_case_c(self):

        print(f"测试用例C")

        assert 28 > 12


    @pytest.mark.dependency(depends=['test_case_a'])

    def test_case_d(self):

        print(f"测试用例D")

        assert 28 > 12


    def test_case_e(self):

        print(f"测试用例E")

        assert 28 > 12

```

运行结果:


## pip install pytest-xdist 分布式并发执行测试用例

测试用例一共有100条,一个执行1分钟,就需要100分钟,如果并行测试10个人一起执行时间就会缩短,这就是一种并行测试,分布式场景;

此方法的应用存在一定的原则,第一,就是用例之间是相互独立的,用例之间没有相互依赖关系,用例可以完全独立运行;第二,用例执行没有顺序,随机顺序都能正常执行;第三,每个测试用例都能重复运行,运行结果不会影响其他测试用例

此应用方式测试用例较多的时候测试效果明显,在执行过程中使用pytest -n 3命令进行执行

示例中的执行效果不明显

## **pip install pytest-rerunfailures 失败重跑**

使用命令pytest test_a.py --reruns 5 --reruns-delay 1 -vs

可以看出失败的用例执行了5次


```python

import pytest


class Test_A():


    @pytest.mark.parametrize("a, b", [(1, 2), (3, 3), (5, 5)])

    def test_case01(self, a, b):

        print(f"测试用例1")

        assert a == b

```

**pip install pytest-assume 多重校验**

一个方法中写了多条断言,通常第一条过不去,下面的就不执行了,我们希望第一条报错之后,后面的也能够正常运行

使用pytest.assume(),代码如下:


```python

import pytest


class Test_A():


    def test_case01(self):

        print(f"测试用例1")

        pytest.assume(1 > 2)

        pytest.assume(1 < 1)

```


## pip intall pytest-html 测试报告

使用命令pytest -v -s --html=report.html --self-contained-html

浏览器打开


## 测试数据驱动:

也就是我们可以把数据写入到一个yaml文件中进行测试

新建一个data,yaml文件,内容如下

测试用例代码如下:


```python

import yaml

import pytest


with open("./data.yaml") as f:

    datas = yaml.safe_load(f)

    myids = datas.keys()

    mydatas = datas.values()



class Test_A():


    @pytest.mark.parametrize("a, b", mydatas, ids=myids)

    def test_case_a(self, a, b):

        print("测试用例A")

        assert a > b

```

运行结果我们发现可以运行成功,如下


## 测试步骤驱动:

我们在进行自动化的时候需要定位元素,定位元素的时候我们会经常使用find_element方式,因此我们封装该方法到一个类里面,或者使之成为一个单独的方法,之后我们再进行元素定位的时候就可以调用这个方法进行元素定位,这个过程我们称之为测试步骤驱动,简单理解为我们basepage类里面封装的方法


## pytest的高级用法

我们可以利用已有的hook函数来定义我们自己的插件,并把它放在conftest.py文件中作为自己的本地插件,实现我们想要的各种需求

hook函数地址:https://docs.pytest.org/en/latest/_modules/_pytest/hookspec.html


**场景一:

pytest_collection_modifyitems收集上来的测试用例实现定制化功能,解决的问题是:自定义用例的顺序,解决编码问题以及自动添加标签**

我们在conftest.py文件里面添加如下内容:


```python

from typing import List

import pytest


def pytest_collection_modifyitems(

    session: "Session", config: "Config", items: List["Item"]

) -> None:

    print(items)

    items.reverse()

```

使用pytest -vs运行测试用例后:

对比之前的测试用例

我们使用数据化驱动的时候,yaml文件中如果含有中文,那么运行结果会显示乱码,也就是会显示这样:

为了正常能够显示中文,我们需要添加如下代码在conftest.py文件中

item.name = item.name.encode('utf-8').decode('unicode-escape')

item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

conftest.py代码:

```python

from typing import List

import pytest


def pytest_collection_modifyitems(

    session: "Session", config: "Config", items: List["Item"]

) -> None:

    print(items)

    # items.reverse()

    for item in items:

        item.name = item.name.encode('utf-8').decode('unicode-escape')

        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

```

data.yaml文件内容:


```python

整数:

  - 12

  - 11

float:

  - 0.68

  - 0.6

```

test_a.py:


```python

import pytest

import yaml

import pytest


with open("./data.yaml", encoding='utf-8') as f:

    datas = yaml.safe_load(f)

    print(datas)

    myids = datas.keys()

    mydatas = datas.values()



class Test_A():


    @pytest.mark.parametrize("a, b", mydatas, ids=myids)

    def test_case_a(self, a, b):

        print("测试用例A")

        print(datas)

        assert a > b

```

运行之后显示了正常了:

当然也可以自动添加标签,然后可以运行某个对应的标签的代码

修改conftest.py代码

        if 'case_a' in item._nodeid:

            item.add_marker(pytest.mark.case_a)

        if 'case_b' in item._nodeid:

            item.add_marker(pytest.mark.case_b)

```python

from typing import List

import pytest


def pytest_collection_modifyitems(

    session: "Session", config: "Config", items: List["Item"]

) -> None:

    print(items)

    # items.reverse()

    for item in items:

        item.name = item.name.encode('utf-8').decode('unicode-escape')

        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')  #_nodeid测试用例名称

        if 'case_a' in item._nodeid:

            item.add_marker(pytest.mark.case_a)


        if 'case_b' in item._nodeid:

            item.add_marker(pytest.mark.case_b)

```

test_a.py文件还是这样


```python

import pytest

import yaml

import pytest


with open("./data.yaml", encoding='utf-8') as f:

    datas = yaml.safe_load(f)

    print(datas)

    myids = datas.keys()

    mydatas = datas.values()



class Test_A():


    @pytest.mark.parametrize("a, b", mydatas, ids=myids)

    def test_case_a(self, a, b):

        print("测试用例A")

        assert a > b


    def test_case_b(self):

        print(f"测试用例B")

        assert 9 > 7

```

使用命令pytest test_a.py -m "case_b" -vs只运行case_b标签的测试用例

**我们在运行测试用例的时候,也可以只运行我们上次运行失败的用例,使用参数

--lf, --last-failed 只重新运行上次运行失败的用例(或如果没有失败的话会全部跑)

--ff, --failed-first 运行所有测试,但首先运行上次运行失败的测试(这可能会重新测试,从而导致重复的fixture setup/teardown)**

这里就不给大家举例子了


**场景二:

我们可以使用pytest_addoption 自定义命令行参数,比如说我们需要在不同的环境中去运行我们的测试用例,那么我们就可以通过命令行去传递不同的环境标识,去得到我们想要的测试结果:**

我们在conftest.py文件中编辑这些代码

def pytest_addoption(parser):   #parser: 用户命令行参数与ini文件值的解析器

    mygroup = parser.getgroup("learn")  # group 将下面所有的 option都展示在这个group下。

    mygroup.addoption("--env01",  # 注册一个命令行选项

                      default='test',

                      dest='env01',

                      help='set your run env'

                      )

    mygroup.addoption("--env02",  # 注册一个命令行选项

                      default='test',

                      dest='env02',

                      help='set your run env'

                      )


#通过命令行来处理传递不同的参数,设置成fixture,将test环境和dev环境或者其他环境分别处理,获取想要的不同环境下的数据

@pytest.fixture(scope='session')

def cmdoption(request):

    myenv = request.config.getoption("--env", default='test')

    if myenv == 'test':

        datapath = 'datas/test/datas.yaml'


    if myenv == 'dev':

        datapath = 'datas/dev/datas.yaml'


    with open(datapath) as f:

        datas = yaml.safe_load(f)

    return myenv,datas

```python

from typing import List

import pytest

import yaml



def pytest_collection_modifyitems(

    session: "Session", config: "Config", items: List["Item"]

) -> None:

    print(items)

    # items.reverse()

    for item in items:

        item.name = item.name.encode('utf-8').decode('unicode-escape')

        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')  #_nodeid测试用例名称

        if 'case_a' in item._nodeid:

            item.add_marker(pytest.mark.case_a)


        if 'case_b' in item._nodeid:

            item.add_marker(pytest.mark.case_b)


def pytest_addoption(parser):   #parser: 用户命令行参数与ini文件值的解析器

    mygroup = parser.getgroup("learn")  # group 将下面所有的 option都展示在这个group下。

    mygroup.addoption("--env01",  # 注册一个命令行选项

                      default='test',

                      dest='env01',

                      help='set your run env'

                      )

    mygroup.addoption("--env02",  # 注册一个命令行选项

                      default='test',

                      dest='env02',

                      help='set your run env'

                      )


#通过命令行来处理传递不同的参数,设置成fixture,将test环境和dev环境或者其他环境分别处理,获取想要的不同环境下的数据

@pytest.fixture(scope='session')

def cmdoption(request):

    myenv = request.config.getoption("--env", default='test')

    if myenv == 'test':

        datapath = 'datas/test/datas.yaml'


    if myenv == 'dev':

        datapath = 'datas/dev/datas.yaml'


    with open(datapath) as f:

        datas = yaml.safe_load(f)

    return myenv,datas

```

设置文件datas/test/datas.yaml内容如下:


```python

test:

  ip: 192.168.21.20

  port: 3306


```

设置文件datas/dev/datas.yaml内容如下:


```python

dev:

  ip: 10.20.2.1

  port: 3309

```

新建一个测试用例test_addoption.py:


```python

def test_addoption(cmdoption):

    env, datas = cmdoption

    print(f"{env},{datas}")

    print(type(datas))

    ip = datas[env]['ip']

    print(ip)

    port = datas[env]['port']

    url = "http://"+str(ip)+":"+str(port)

    print(url)

```

我们使用pytest --help会发现在帮助文档中有我们自己设置的环境参数

之后我们使用命令pytest test_addoption.py --env02 test -vs运行该测试用例,发现能够正常运行

**场景三:参数化简化

pytest_generate_tests可以实现自定义动态参数化方案或者扩展,也就是我们重写这个hook函数即可,说白了,只要我们用到了参数化,都可以考虑这个功能是否能够给我们带来一些方便**

在conftest.py里面最后添加如下内容

def pytest_generate_tests(metafunc: "Metafunc") -> None:

    if "param" in metafunc.fixturenames:

        metafunc.parametrize("param", metafunc.module.data_params, ids=metafunc.module.dataids, scope='function')

```python

from typing import List

import pytest

import yaml



def pytest_collection_modifyitems(

    session: "Session", config: "Config", items: List["Item"]

) -> None:

    print(items)

    # items.reverse()

    for item in items:

        item.name = item.name.encode('utf-8').decode('unicode-escape')

        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')  #_nodeid测试用例名称

        if 'case_a' in item._nodeid:

            item.add_marker(pytest.mark.case_a)


        if 'case_b' in item._nodeid:

            item.add_marker(pytest.mark.case_b)


def pytest_addoption(parser):   #parser: 用户命令行参数与ini文件值的解析器

    mygroup = parser.getgroup("learn")  # group 将下面所有的 option都展示在这个group下。

    mygroup.addoption("--env01",  # 注册一个命令行选项

                      default='test',

                      dest='env01',

                      help='set your run env'

                      )

    mygroup.addoption("--env02",  # 注册一个命令行选项

                      default='test',

                      dest='env02',

                      help='set your run env'

                      )


#通过命令行来处理传递不同的参数,设置成fixture,将test环境和dev环境或者其他环境分别处理,获取想要的不同环境下的数据

@pytest.fixture(scope='session')

def cmdoption(request):

    myenv = request.config.getoption("--env", default='test')

    if myenv == 'test':

        datapath = 'datas/test/datas.yaml'


    if myenv == 'dev':

        datapath = 'datas/dev/datas.yaml'


    with open(datapath) as f:

        datas = yaml.safe_load(f)

    return myenv,datas


#

def pytest_generate_tests(metafunc: "Metafunc") -> None:

    if "param" in metafunc.fixturenames:

        metafunc.parametrize("param", metafunc.module.data_params, ids=metafunc.module.dataids, scope='function')

```

新建一个test_param.py文件,内容如下


```python

import yaml


with open("./data_params.yaml") as f:

    data = yaml.safe_load(f)

    data_params = data.values()

    dataids = data.keys()



def test_param(param):

    print(f"{param}")

```

新建一个./data_params.yaml文件,内容如下:


```python

test1: [1, 2, 3]

test2: [4, 5, 6]

test3: [7, 8, 9]

```

我们运行这个test_param.py文件

***这里我们需要注意的是:

测试用例里面的参数名要和conftest.py文件中pytest_generate_tests方法中的param名字要一致,可以自定义这个名字,前后一致即可

conftest.py文件中pytest_generate_tests方法中的data_params和dataids要和测试用例中的data_params和dataids也要一致,就像我们这个例子中的conftest.py和test_param.py这两个文件一致即可***


## 6、allure测试报告:

allure是一个轻量级灵活的支持多语言的测试报告工具,java语言开发,支持pytest, javascript, php, ruby等,也可以集成到jenkins,在pycharm中我们需要安装allure-pytest(或者pip install allure-pytest)

在测试执行期间收集结果

**pytest [测试文件] -s -q --alluredir=./resullt/(--alluredir这个选项用于指定存储测试结果的路径)**

查看报告

**allure serve ./result/**

常用的特性

@feature添加功能名称

@story添加子功能名称

@step添加步骤细节

@attach天机具体的文本信息(图片、视频、网页等)


```python

import allure


@allure.feature("加购模块")

class TestA():


    @allure.story("第一条用例")

    def test_case1(self):

        print("测试用例1")


    @allure.story("第二条用例")

    def test_case2(self):

        print("测试用例2")


    @allure.story("第三条用例")

    def test_case3(self):

        print("测试用例3")


    @allure.story("第四条用例")

    def test_case4(self):

        print("测试用例4")


@allure.feature("结算模块")

class TestB():


    @allure.story("结算模块第一条用例")

    def test_case1(self):

        print("结算模块测试用例1")


    @allure.story("结算模块第二条用例")

    def test_case2(self):

        print("结算模块测试用例2")

```

只执行结算模块的测试用例

***pytest test_a.py --allure-features="结算模块" -vs***

**只执行结算模块第二条用例

pytest test_a.py --allure-stories="结算模块第二条用例" -vs**

我们在源代码里面添加测试步骤:

```python

import allure


@allure.feature("加购模块")

class TestA():


    @allure.story("第一条用例")

    def test_case1(self):

        with allure.step("步骤一:选择商品"):

            print("选择商品")


        with allure.step("步骤二:点击加入购物车"):

            print("点击加入购物车")

        print("测试用例1")


    @allure.story("第二条用例")

    def test_case2(self):

        print("测试用例2")


    @allure.story("第三条用例")

    def test_case3(self):

        print("测试用例3")


    @allure.story("第四条用例")

    def test_case4(self):

        print("测试用例4")


@allure.feature("结算模块")

class TestB():


    @allure.story("结算模块第一条用例")

    def test_case1(self):

        print("结算模块测试用例1")


    @allure.story("结算模块第二条用例")

    def test_case2(self):

        print("结算模块测试用例2")

```

**只运行架构模块

pytest test_a.py --allure-features="加购模块" -vs**

执行生成一个测试结果

**pytest test_a.py --allure-features="加购模块" -vs --alluredir=./result**

这里记录了我们每一条测试用例的执行结果

**使用allure serve ./result命令生成测试报告**

在测试报告中加入一个测试用例的链接地址,这里我们使用https://www.baidu.com/为例

修改源码如下

    **test_link = "https://www.baidu.com/"

    @allure.testcase(test_link, "加购模块第二条测试用例")**

```python

import allure


@allure.feature("加购模块")

class TestA():


    @allure.story("第一条用例")

    def test_case1(self):

        with allure.step("步骤一:选择商品"):

            print("选择商品")


        with allure.step("步骤二:点击加入购物车"):

            print("点击加入购物车")

        print("测试用例1")

    test_link = "https://www.baidu.com/"

    @allure.testcase(test_link, "加购模块第二条测试用例")

    def test_case2(self):

        print("测试用例2")


    @allure.story("第三条用例")

    def test_case3(self):

        print("测试用例3")


    @allure.story("第四条用例")

    def test_case4(self):

        print("测试用例4")

```

运行如下:

**pytest test_a.py --allure-features="加购模块" -vs --alluredir=./result1

allure serve ./result1**

使用allure serve ./result1是直接唤起浏览器,生成一个测试报告,如果我们要在本地直接生成一个html文件呢,我们可以使用

**allure generate ./result1**

本地会生成一个allure-report文件

右键打开index.html,这个是我们想要的生成的测试报告文件

我们指定生成一个哪一个文件下面,假设我们指定生成report文件里面,使用命令

**allure generate ./result1 -o report**

## 按照重要性级别进行一定范围测试

级别:Trivial-不重要  Minor不太重要  Normal 正常问题   Critical严重   Blocker:阻塞

在方法函数和类上面加@allure.severity(allure.severity_level.TRIVIAL)

**执行时 pytest -s -v 文件名 --allure-severities="normal,critical"**

```python

import allure

#@allure.feature("加购模块")

class TestA():


    @allure.severity(allure.severity_level.CRITICAL)

    def test_case1(self):

        with allure.step("步骤一:选择商品"):

            print("选择商品")


        with allure.step("步骤二:点击加入购物车"):

            print("点击加入购物车")

        print("测试用例1")


    @allure.severity(allure.severity_level.MINOR)

    def test_case2(self):

        print("测试用例2")


    @allure.severity(allure.severity_level.NORMAL)

    def test_case3(self):

        print("测试用例3")


    @allure.severity(allure.severity_level.BLOCKER)

    def test_case4(self):

        print("测试用例4")

```

执行结果:


## 我们希望不适用方法名命名我们的测试报告的标题,也就是如图所示的位置

**修改代码如下@allure.title("加购第一条用例"):**


```python

import allure

#@allure.feature("加购模块")

class TestA():


    @allure.title("加购第一条用例")

    def test_case1(self):

        with allure.step("步骤一:选择商品"):

            print("选择商品")


        with allure.step("步骤二:点击加入购物车"):

            print("点击加入购物车")

        print("测试用例1")


    @allure.severity(allure.severity_level.MINOR)

    def test_case2(self):

        print("测试用例2")


    @allure.severity(allure.severity_level.NORMAL)

    def test_case3(self):

        print("测试用例3")


    @allure.severity(allure.severity_level.BLOCKER)

    def test_case4(self):

        print("测试用例4")


```

使用**pytest test_a.py --alluredir=./result3**

生成测试结果

使用**allure serve ./result3**生成测试报告

添加文本,html代码块,截图和视频

代码修改如下


```python

import allure

#@allure.feature("加购模块")

class TestA():


    @allure.title("加购第一条用例")

    def test_case1(self):

        allure.attach("这是一个纯文本", attachment_type=allure.attachment_type.TEXT)


    def test_case2(self):

        print("测试用例2")

        allure.attach("<body>这是一段htmlbody代码块</body>", "html网页", attachment_type=allure.attachment_type.HTML)


    def test_case3(self):

        print("测试用例3")

        allure.attach.file("E:\hewangtong\picture\\300-220.jpg", name = "这是图片", attachment_type=allure.attachment_type.JPG)


    def test_case4(self):

        print("测试用例4")

        allure.attach.file("E:\hewangtong\VIDEO\\《更完善的中后台微前端解决方案-qiankun》.mp4", name = "这是一个视频", attachment_type=allure.attachment_type.MP4)

```

使用**pytest test_a.py --alluredir=./result4**命令生成测试结果

使用**allure serve ./result4**命令生成测试报告

我们也可以本地起一个服务,方便其他同学访问到我们的测试报告

allure open -h 127.0.0.1 -p 8880 ./report/

浏览器里面输入地址http://127.0.0.1:8880/index.html即可访问对应的测试报告



投诉或建议