自动化测试神器:Python之Pytest库入门使用

简介: 自动化测试神器:Python之Pytest库入门使用

本文写作思路和建议:
1、本文从Python的Pytest库基本安装使用开始讲起,详细说明pytest如何操作,如何快速入门?
2、同时说明了pytest的常用特性,如何在自动化测试中进行应用,达到应有的测试效率?
3、建议:阅读本文基本可以掌握Pytest的用法,另外学习的时候建议和Unittest库进行对比着使用,将会达到更好的效果。

1 pytest简介、安装和用例运行

1.1 pytest简介

  • pytest是Python的一个单元测试框架,与python自带的unittest测试框架类似;
  • pytest比unittest框架使用起来更简洁,效率更高,而且特性比较多,也就非常的灵活;
  • 比如pytest常用的特性有:

① 对case可以进行设置跳过,也可以进行标记(比如失败等);
② 可以重复执行失败的case;
③ 可以兼容执行unittest编写的case;
④ 有很多第三方的插件,比如报告allure等;
⑤ 支持持续集成;
⑥ 和unittest一样支持参数化,但Pytest方法更多,更灵活;
。。。

1.2 Pytest安装

  • 直接使用命令即可:

pip install -U pytest

  • 可以使用以下命令查看pytest的版本号:

pip show pytest

  • 需要注意的是,pytest对于Python版本是有要求的,目前最新版本的pytest需要Python在3.8及以上版本。

1.3 pytest如何运行用例?

  • 首先看下pytest运行用例规则:

A、文件名规则:test_*.py和 *_test.py命名的函数;
B、函数名规则:以test_开头的函数;
C、python包的规则:同python一样,包需要有__init__.py文件;
D、静默运行:以-q或-quiet参数进行静默运行函数;

  • 运行方式:

1、通过文件名去运行,比如在代码中加if __name == 'main__':
pytest.main("-s", "test_mm.py");
2、通过命令行调用运行,直接用pytest -s test_mm.py;
3、直接匹配某个目录下所有符合规则的case去运行,比如pytest -vs,或者将规则写入pytest.ini文件中。

  • 举个例子看下运行效果,以下脚本命名为test_mm.py:
# test_mm.py
# -*- coding:utf-8 -*-

import pytest

class TestClass:

    def test_you(self):
        y = "you"
        assert "y" in y

    def test_hai(self):
        h = "hai"
        assert "gg" not in h


if __name__ == '__main__':
    pytest.main(["-s", "test_mm.py"])

# 输出:
# test_mm1.py ..
# ============================== 2 passed in 0.08s ==============================

2 pytest的setup、teardown特性

  • pytest前置和后置就是告诉用例运行前应该做啥,运行完后应该做啥;
  • 和unittest有一些方法是一样的;
  • pytest有十种前置和后置方法:
方法 运行级别 说明
setup_module() 模块级别 整个.py模块开始前只执行一次,如打开一次浏览器
teardown_module() 模块级别 整个.py模块结束后只执行一次,如关闭一次浏览器
setup_function() 函数级别 每个函数级别用例开始前都执行,此方法不在类中
teardown_function() 函数级别 每个函数级别用例结束后都执行,此方法不在类中
setup_class() 级别 整个测试类开始前只执行一次,和Unittest基本一样
teardown_class() 级别 整个测试类结束后只执行一次,和Unittest基本一样
setup_method() 方法级别 里面每个用例执行都会执行
teardown_method() 方法级别 里面每个用例结束都会执行
setup() 方法细化级别 里面每个用例执行都会执行
teardown() 方法细化级别 里面每个用例结束都会执行
  • 咱们来看一个示例,文件命名为test_set_tear.py:
# -*- coding:utf-8 -*-

import pytest

def setup_module():
    print("setup_module:整个.py模块开始前只执行一次")

def teardown_module():
    print("teardown_module:整个.py模块结束后只执行一次")

def setup_function():
    print("setup_function:每个函数级别用例开始前都执行")

def teardown_function():
    print("teardown_function:每个函数级别用例结束后都执行")

def test_one():
    print("用例1")

def test_two():
    print("用例2")

class TestOne():

    def setup_class(self):
        print("setup_class:整个测试类开始前只执行一次")

    def teardown_class(self):
        print("teardown_class:整个测试类结束后只执行一次")

    def setup_method(self):
        print("setup_method:类里面每个用例执行前都会执行")

    def teardown_method(self):
        print("teardown_method:类里面每个用例结束后都会执行")

    def setup(self):
        print("setup:类里面每个用例执行前都会执行")

    def teardown(self):
        print("teardown:类里面每个用例结束后都会执行")

    def test_thr(self):
        print("用例3")

    def test_fo(self):
        print("用例4")

if __name__ == "__main__":
    pytest.main(["-s", "test_set_tear.py"])

# 输出为:
# setup_module:整个.py模块开始前只执行一次
# setup_function:每个函数级别用例开始前都执行
# 用例1
# .teardown_function:每个函数级别用例结束后都执行
# setup_function:每个函数级别用例开始前都执行
# 用例2
# .teardown_function:每个函数级别用例结束后都执行
# setup_class:整个测试类开始前只执行一次
# setup_method:类里面每个用例执行前都会执行
# setup:类里面每个用例执行前都会执行
# 用例3
# .teardown:类里面每个用例结束后都会执行
# teardown_method:类里面每个用例结束后都会执行
# setup_method:类里面每个用例执行前都会执行
# setup:类里面每个用例执行前都会执行
# 用例4
# .teardown:类里面每个用例结束后都会执行
# teardown_method:类里面每个用例结束后都会执行
# teardown_class:整个测试类结束后只执行一次
# teardown_module:整个.py模块结束后只执行一次

4 passed in 0.14s

3 pytest如何进行用例断言?

  • pytest中的断言就使用assert即可;
  • pytest的常用断言方式有以下几种:
断言 说明
assert a 判断 a为真
assert not a 判断 a不为真
assert a in b 判断 b 包含 a
assert a == b 判断 a 等于 b
assert a != b 判断 a 不等于 b
  • 看一个示例,把以下脚本命名为:test_assert.py:
# -*- coding:utf-8 -*-

import pytest

class TestU():

    def test_f(self):
        a = 3
        b = 4
        s = a + b
        return s

    def test_func(self):
        assert self.test_f() == 7, "计算结果不是7"

if __name__ == "__main__":
    pytest.main(["-s", "test_assert.py"])

# 输出为:
# test_assert.py ..               [100%]
# ================== 2 passed in 0.31s ====================

4 pytest中的fixture特性

4.1 fixture简介

  • 和setup、teardown的区别是:fixture可自定义测试用例的前置条件
  • setup、teardown针对整个脚本全局生效,可实现在执行用例前后加入一些操作;
  • setup、teardown不能做到灵活使用,比如用例A先登陆,用例B不需要登陆,用例C需要登陆,这样使用fixture更容易实现功能。

4.2 fixture参数

参数原型:fixture(scope="function", params=None, autouse=False, ids=None, name=None):

  • 关于参数解释如下:
参数 说明
scope 默认:function,还有class、module、package、session
autouse 默认:False,手动调用该fixture;为True,所有作用域内的测试用例都会自动调用该fixture
params 一个可选的参数列表
ids 每个字符串id的列表
name fixture的名称, 默认为装饰函数的名称,同一模块的fixture相互调用建议写个不同的name

4.3 示例说明

  • 关于用法直接参考上边的参数说明即可;
  • 这里我们用一个例子来进行说明,以下代码写入脚本test_mfixture.py:
# -*- coding:utf-8 -*-

import pytest

# 不带参数时默认scope="function"
@pytest.fixture
def case():
    print("这个是登陆功能!")

def test_one(case):
    print("用例1需要登陆,然后进行操作one")

def test_two():
    print("用例2不需要登陆,直接操作two")

@pytest.fixture
def case1():
    print("输入验证码")

def test_three(case):
    print("用例3需要登陆,然后操作three")

@pytest.mark.usefixtures("case", "case1")
def test_four(case1):
    print("先登录,再输入验证码,最后操作four")

@pytest.fixture(autouse=True)
def case2():
    print("所有用例都会调用case2")

if __name__ == "__main__":
    pytest.main(["-s", "test_mfixture.py"])

# 输出为:
# test_mfixture.py::test_one                    所有用例都会调用case2
#                                              这个是登陆功能!
#PASSED                                        [ 25%]用例1需要登陆,然后进行操作one

#test_mfixture.py::test_two                    所有用例都会调用case2
#PASSED                                        [ 50%]用例2不需要登陆,直接操作two

#test_mfixture.py::test_three                  所有用例都会调用case2
#                                              这个是登陆功能!
#PASSED                                        [ 75%]用例3需要登陆,然后操作three

#test_mfixture.py::test_four                   所有用例都会调用case2
#                                              这个是登陆功能!
#                                             输入验证码
#PASSED                                       [100%]先登录,再输入验证码,最后操作four

#=========== 4 passed in 0.03s ==========

5 pytest如何跳过用例执行?

  • 在Pytest中也提供了两种方式进行用例的跳过 skip、skipif;
  • pytest.skip()不同于pytest.mark.skip,pytest.mark.skip是作用于整个测试用例;而 pytest.skip()是测试用例执行期间强制跳过不再执行剩余内容;
    和Python中break 跳出循环类似。
  • 一个示例简单说明下,脚本命名为test_pytest_skip1.py:
# -*- coding:utf-8 -*-

import pytest
import time

@pytest.fixture()
def start():
    print("打开浏览器,输入用户名和密码登陆")
    yield
    print("关闭浏览器")

def test_1(start):
    print("用例1......")
    i = 1
    while True:
        print(time.time())
        i += 1
        if i == 6:
            pytest.skip("打印5次时间后,第六次不再打印了~")

if __name__ == '__main__':
    pytest.main(["-s", "test_pytest_skip1.py"])

# 输出为:
# test_pytest_skip1.py::test_1 打开浏览器,输入用户名和密码登陆
# SKIPPED (打印5次时间后,第六次不再打印了~)  [100%]用例1......
# 1668677189.0525532
# 1668677189.0525532
# 1668677189.0525532
# 1668677189.0525532
# 1668677189.0525532

# Skipped: 打印5次时间后,第六次不再打印了~
# 关闭浏览器


# ======== 1 skipped in 0.02s ===========

6 pytest的mark特性

  • pytest可自定义标记,即进行mark;
  • 作用是把一个大项目自动化用例,划分多个模块,标明哪些是模块A用例,哪些是模块B的,运行代码时候指定mark名称运行就可以;
  • 使用方法为:

@pytest.mark.自定义名称

  • 一个示例,脚本为test_mark.py:
# -*- coding:utf-8 -*-

import pytest

@pytest.mark.login
def test_login():
    print("用户登陆")

@pytest.mark.case_a
def test_case_a():
    print("执行用例a")

@pytest.mark.case_b
def test_case_b():
    print("执行用例b")

@pytest.mark.quit
def test_quit():
    print("用户退出")

运行规则如下:
1、运行一个标记:pytest -s -m login test_mark.py;
2、运行多个标记:pytest -s -m "login or case_a or case_b or quit" test_mark.py;
3、不运行某个标记,直接取反即可:pytest -s -m "not quit" test_mark.py

7 pytest参数化如何使用?

  • pytest允许在多个级别启用测试参数化;
  • pytest.fixture() 允许fixture有参数化功能;
  • @pytest.mark.parametrize 允许在测试函数或类中定义多组参数和fixtures;
  • pytest_generate_tests 允许定义自定义参数化方案或扩展。

7.1 parametrize方法

  • 参数说明:

parametrize(argnames, argvalues, indirect=False, ids=None, scope=None);

参数 说明 格式 备注
argnames 参数名称 字符串"arg1,arg2,arg3" 也可以list或者tuple
argvalues 参数值列表 val1,val2,val3 多参数用元组存放 (val1,val2), (val3, val4)
indirect 设置成True,则把传进来的参数当函数执行,而不是一个参数 / /
ids 用例的ID 字符串列表 ids的长度需要与测试数据列表的长度一致
scope 用于控制Fixture的作用范围 / 默认"function"

7.2 使用方法

  • 示例如下,脚本为test_pytest_parametrize.py:
# -*- coding:utf-8 -*-
import pytest

@pytest.mark.parametrize("num, result", [("10 + 10", 20),
                                         ("30 - 10", 20),
                                         ("4 * 5", 20),
                                         ("40 / 2", 20)])
def test_case(num, result):
    print(f"num:{num}")
    print(f"result:{result}")
    assert eval(num) == result

if __name__ == '__main__':
    pytest.main(["-s", "test_pytest_parametrize.py"])

# 输出为:
# test_pytest_parametrize.py 
# num:10 + 10
# result:20
# .
# num:30 - 10
# result:20
# .
# num:4 * 5
# result:20
# .
# num:40 / 2
# result:20
# .

8 总结及说明

除了以上提及的,pytest还有其他很多特性,或者很多第三方插件,这里不再赘述了,比如有;

  • 用例失败重跑可以使用插件pytest-rerunfailures来实现;
  • pytest-HTML是一个插件,pytest用于生成测试结果的HTML报告;
  • 为了重复执行用例,我们可以使用pytest-repeat插件;
  • pytest.ini是一个固定的文件,用来读取配置信息;
  • 使用pytest-assume插件来解决多重断言;
  • pytest-xdist插件可以让自动化测试用例分布式执行,节省测试时间,属于进程级别的并发;
  • allure-pytest插件可以生成完美的自动化可视化报告。
目录
相关文章
|
6天前
|
数据采集 存储 XML
Python爬虫定义入门知识
Python爬虫是用于自动化抓取互联网数据的程序。其基本概念包括爬虫、请求、响应和解析。常用库有Requests、BeautifulSoup、Scrapy和Selenium。工作流程包括发送请求、接收响应、解析数据和存储数据。注意事项包括遵守Robots协议、避免过度请求、处理异常和确保数据合法性。Python爬虫强大而灵活,但使用时需遵守法律法规。
|
7天前
|
Python
深入理解Python装饰器:从入门到实践####
本文旨在通过简明扼要的方式,为读者揭开Python装饰器的神秘面纱,从基本概念、工作原理到实际应用场景进行全面解析。不同于常规的摘要仅概述内容概要,本文将直接以一段精炼代码示例开篇,展示装饰器如何优雅地增强函数功能,激发读者探索兴趣,随后深入探讨其背后的机制与高级用法。 ####
37 11
|
4天前
|
机器学习/深度学习 人工智能 TensorFlow
人工智能浪潮下的自我修养:从Python编程入门到深度学习实践
【10月更文挑战第39天】本文旨在为初学者提供一条清晰的道路,从Python基础语法的掌握到深度学习领域的探索。我们将通过简明扼要的语言和实际代码示例,引导读者逐步构建起对人工智能技术的理解和应用能力。文章不仅涵盖Python编程的基础,还将深入探讨深度学习的核心概念、工具和实战技巧,帮助读者在AI的浪潮中找到自己的位置。
|
4天前
|
机器学习/深度学习 数据挖掘 Python
Python编程入门——从零开始构建你的第一个程序
【10月更文挑战第39天】本文将带你走进Python的世界,通过简单易懂的语言和实际的代码示例,让你快速掌握Python的基础语法。无论你是编程新手还是想学习新语言的老手,这篇文章都能为你提供有价值的信息。我们将从变量、数据类型、控制结构等基本概念入手,逐步过渡到函数、模块等高级特性,最后通过一个综合示例来巩固所学知识。让我们一起开启Python编程之旅吧!
|
4天前
|
存储 Python
Python编程入门:打造你的第一个程序
【10月更文挑战第39天】在数字时代的浪潮中,掌握编程技能如同掌握了一门新时代的语言。本文将引导你步入Python编程的奇妙世界,从零基础出发,一步步构建你的第一个程序。我们将探索编程的基本概念,通过简单示例理解变量、数据类型和控制结构,最终实现一个简单的猜数字游戏。这不仅是一段代码的旅程,更是逻辑思维和问题解决能力的锻炼之旅。准备好了吗?让我们开始吧!
|
10天前
|
Java 测试技术 持续交付
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
本文重点讲解如何搭建App自动化测试框架的思路,而非完整源码。主要内容包括实现目的、框架设计、环境依赖和框架的主要组成部分。适用于初学者,旨在帮助其快速掌握App自动化测试的基本技能。文中详细介绍了从需求分析到技术栈选择,再到具体模块的封装与实现,包括登录、截图、日志、测试报告和邮件服务等。同时提供了运行效果的展示,便于理解和实践。
44 4
【入门思路】基于Python+Unittest+Appium+Excel+BeautifulReport的App/移动端UI自动化测试框架搭建思路
|
3天前
|
设计模式 缓存 开发框架
Python中的装饰器:从入门到实践####
本文深入探讨了Python中装饰器的工作原理与应用,通过具体案例展示了如何利用装饰器增强函数功能、提高代码复用性和可读性。读者将学习到装饰器的基本概念、实现方法及其在实际项目开发中的实用技巧。 ####
16 3
|
7天前
|
机器学习/深度学习 数据采集 数据可视化
Python在数据科学中的应用:从入门到实践
本文旨在为读者提供一个Python在数据科学领域应用的全面概览。我们将从Python的基础语法开始,逐步深入到数据处理、分析和可视化的高级技术。文章不仅涵盖了Python中常用的数据科学库,如NumPy、Pandas和Matplotlib,还探讨了机器学习库Scikit-learn的使用。通过实际案例分析,本文将展示如何利用Python进行数据清洗、特征工程、模型训练和结果评估。此外,我们还将探讨Python在大数据处理中的应用,以及如何通过集成学习和深度学习技术来提升数据分析的准确性和效率。
|
5天前
|
机器学习/深度学习 数据挖掘 开发者
Python编程入门:理解基础语法与编写第一个程序
【10月更文挑战第37天】本文旨在为初学者提供Python编程的初步了解,通过简明的语言和直观的例子,引导读者掌握Python的基础语法,并完成一个简单的程序。我们将从变量、数据类型到控制结构,逐步展开讲解,确保即使是编程新手也能轻松跟上。文章末尾附有完整代码示例,供读者参考和实践。
|
6天前
|
人工智能 数据挖掘 程序员
Python编程入门:从零到英雄
【10月更文挑战第37天】本文将引导你走进Python编程的世界,无论你是初学者还是有一定基础的开发者,都能从中受益。我们将从最基础的语法开始讲解,逐步深入到更复杂的主题,如数据结构、面向对象编程和网络编程等。通过本文的学习,你将能够编写出自己的Python程序,实现各种功能。让我们一起踏上Python编程之旅吧!