79节

目录

1.pytest 筛选用例

2.pytest的断言 assert

3.测试报告

4.pytest用例执行顺序

5.数据驱动

 

1.pytest 筛选用例:标记功能

1).标签打在整个测试类上面

举例,在上面的登录测试用例的测试类上面加标签:@pytest.mark.login

①在pytest.ini文件中加上标签名:login

②在TestLogin类上面加@pytest.mark.login

③terminal中运行 pytest -m "login"

代码实现:

"""登录功能的测试用例"""

import unittest
import pytest
from middware.handler import HandlerMiddle
from config.config import Wait_time

@pytest.mark.login
class TestLogin(unittest.TestCase):
    """登录功能的测试类"""
    @pytest.mark.error
    def test_login_error(self):
        """登录失败测试步骤
        1.打开浏览器
        2.访问登录页面
        3.元素定位+元素操作,输入用户名和密码,点击登录
        4.通过获取页面内容得到实际结果,进行断言
        :return:
        """

        from selenium import webdriver

        #1.打开浏览器
        driver = webdriver.Chrome()
        #设置隐性等待 等待的时间就可以放在config中,直接参数调用
        ##方法一:放在yaml中
        wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"]
        ##方法二、放在config.py中
        #wait_time = Wait_time
        driver.implicitly_wait(wait_time)

        #2.访问登录页面
        url = "http://120.78.128.25:8765/Index/login.html"
        driver.get(url)

        #3.元素定位+元素操作,输入用户名和密码,点击登录
        driver.find_element_by_name("phone").send_keys("") #定位输入手机号为空
        driver.find_element_by_name("password").send_keys("")#定位输入的密码为空
        driver.find_element_by_class_name("btn-special").click()

        #4.通过获取页面内容得到实际结果,进行断言
        #实际结果是在页面上的提示,再次进行定位
        actual_result = driver.find_element_by_class_name("form-error-info").text

        #断言
        self.assertTrue(actual_result == "请输入手机号")


    # @pytest.mark.success
    def test_login_success(self):
        """登录成功测试用例
        1.打开浏览器
        2.访问登录页面
        3.元素定位+元素操作,输入用户名和密码,点击登录
        4.通过获取页面内容得到实际结果,进行断言
        :return:
        """
        from selenium import webdriver
        #1.打开浏览器
        driver = webdriver.Chrome()

        #设置隐性等待时间
        wait_time  = HandlerMiddle.yaml_data["selenium"]["wait_time"]
        driver.implicitly_wait(wait_time)

        #2.访问登录页面
        url="http://120.78.128.25:8765/Index/login.html"
        driver.get(url)

        #3.元素定位+元素操作,输入用户名和密码,点击登录
        driver.find_element_by_name("phone").send_keys("15*********")
        driver.find_element_by_name("password").send_keys("15")
        driver.find_element_by_class_name("btn-special").click()

        #4.获取实际结果,进行断言
        actual_result = driver.find_element_by_xpath("//a[@href='/Member/index.html']").text
        print(type(actual_result))
        self.assertTrue("我的帐户[小蜜蜂177872141]" in actual_result)

运行结果:

 

 

 2).标记功能组合------不同的testcase的py文件中,可以同时运行多个

语法1.:

pytest -m "register_error or success" -------只需要满足一个条件就可以运行(可以组合2个或者2个以上)

pytest -m "register_error and success" -------2个条件同事满足才可以运行(可以组合2个或者2个以上)

pytest -m "register_error and not success" -------2个条件同事满足才可以运行(可以组合2个或者2个以上),取非

 

举例:运行test_register.py中的register_error,或者test_login中的success

首先别忘记在ini文件中注册tagname

代码实现:

test_register.py:

import unittest
import pytest


class TestRegister(unittest.TestCase):
    """注册功能的测试类"""
    @pytest.mark.register_error
    def test_register_error(self):
        pass

 

test_login.py:

"""登录功能的测试用例"""

import unittest
import pytest
from middware.handler import HandlerMiddle
from config.config import Wait_time

@pytest.mark.login
class TestLogin(unittest.TestCase):
    """登录功能的测试类"""
    @pytest.mark.error
    def test_login_error(self):
        """登录失败测试步骤
        1.打开浏览器
        2.访问登录页面
        3.元素定位+元素操作,输入用户名和密码,点击登录
        4.通过获取页面内容得到实际结果,进行断言
        :return:
        """

        from selenium import webdriver

        #1.打开浏览器
        driver = webdriver.Chrome()
        #设置隐性等待 等待的时间就可以放在config中,直接参数调用
        ##方法一:放在yaml中
        wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"]
        ##方法二、放在config.py中
        #wait_time = Wait_time
        driver.implicitly_wait(wait_time)

        #2.访问登录页面
        url = "http://120.78.128.25:8765/Index/login.html"
        driver.get(url)

        #3.元素定位+元素操作,输入用户名和密码,点击登录
        driver.find_element_by_name("phone").send_keys("") #定位输入手机号为空
        driver.find_element_by_name("password").send_keys("")#定位输入的密码为空
        driver.find_element_by_class_name("btn-special").click()

        #4.通过获取页面内容得到实际结果,进行断言
        #实际结果是在页面上的提示,再次进行定位
        actual_result = driver.find_element_by_class_name("form-error-info").text

        #断言
        self.assertTrue(actual_result == "请输入手机号")

运行pytest -m "register_error or success",结果:

 

3)标记功能组合---------一个函数或者类上面,可以加多个标签

例1: 标签组合and

代码如下:

"""登录功能的测试用例"""

import unittest
import pytest
from middware.handler import HandlerMiddle
from config.config import Wait_time

@pytest.mark.login
class TestLogin(unittest.TestCase):
    """登录功能的测试类"""

@pytest.mark.smoke @pytest.mark.error def test_login_error(self): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver 。 。 。 。

运行:pytest -m "login and smoke" ,类标签有2个方法,但是and smoke,表示只筛选类里面的标记为smoke的方法。、

结果:

 

 

 

例2: 标签组合 not

运行TestLogin这个类下面的success的方法(success方法没有打标签)

运行:pytest -m "login and not smoke"

或者pytest -m "login and not error"

import unittest
import pytest
from middware.handler import HandlerMiddle
from config.config import Wait_time

@pytest.mark.login
class TestLogin(unittest.TestCase):
    """登录功能的测试类"""

@pytest.mark.smoke @pytest.mark.error def test_login_error(self): """登录失败测试步骤 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待 等待的时间就可以放在config中,直接参数调用 ##方法一:放在yaml中 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] ##方法二、放在config.py中 #wait_time = Wait_time driver.implicitly_wait(wait_time) #2.访问登录页面 url = "http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("") #定位输入手机号为空 driver.find_element_by_name("password").send_keys("")#定位输入的密码为空 driver.find_element_by_class_name("btn-special").click() #4.通过获取页面内容得到实际结果,进行断言 #实际结果是在页面上的提示,再次进行定位 actual_result = driver.find_element_by_class_name("form-error-info").text #断言 self.assertTrue(actual_result == "请输入手机号") def test_login_success(self): """登录成功测试用例 1.打开浏览器 2.访问登录页面 3.元素定位+元素操作,输入用户名和密码,点击登录 4.通过获取页面内容得到实际结果,进行断言 :return: """ from selenium import webdriver #1.打开浏览器 driver = webdriver.Chrome() #设置隐性等待时间 wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"] driver.implicitly_wait(wait_time) #2.访问登录页面 url="http://120.78.128.25:8765/Index/login.html" driver.get(url) #3.元素定位+元素操作,输入用户名和密码,点击登录 driver.find_element_by_name("phone").send_keys("15********") driver.find_element_by_name("password").send_keys("15") driver.find_element_by_class_name("btn-special").click() #4.获取实际结果,进行断言 actual_result = driver.find_element_by_xpath("//a[@href='/Member/index.html']").text print(type(actual_result)) self.assertTrue("我的帐户[小蜜蜂177872141]" in actual_result)

 

注意:用例标记的时候,标签如果有逻辑运算,一定要加双引号。

 

2.pytest的断言 assert

背景:上篇博客中有提到,pytest是可以脱离类存在的,所以单个函数的断言,是用不了self.assertTrue

1).pytest 的断言直接用assert即可

   assert 3>2、assert 4=4 这样表述即可。

 

3.测试报告

1).安装HTML的测试报告  pip install pytest-html

2).运行结果生成报告:pytest -m "login and not error" --html=report.html

   即可在项目下生成测试报告。

3).测试报告生成时间戳:脚本运行pytest

  ①在run.py文件中,以pytest.main()形式运行用例。

  首先看下main()方法的源码:参数表示:列表形式的命令行参数;插件暂时用不到,先不看

 

 run.py如下:

"运行测试用例"
import pytest

if __name__ == '__main__':
    pytest.main(["--html=report1.html"])

下面将测试报告加上时间戳:

①import datatime

②ts = datatime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")

run.py实现:

"运行测试用例"
import pytest
import datetime
ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")

if __name__ == '__main__':
    pytest.main(["--html={}report.html".format(ts)])

 

4.pytest用例执行顺序

类里面的用例方法:从上到下,运行(简单来说,想让哪个用例先运行,就把用例写在前面)

 

5.数据驱动  79节45min

首先,回顾下,如果用unittest框架去测试,代码如下:

"""登录功能的测试用例"""
import ddt
import unittest
import pytest
from middware.handler import HandlerMiddle
from config.config import Wait_time

data = HandlerMiddle.excel.read_data("login")

@ddt.ddt
class TestLogin(unittest.TestCase):
    """登录功能的测试类"""
    
    @ddt.data(*data)
    def test_login_error(self,test_info):
        """登录失败测试步骤
        1.打开浏览器
        2.访问登录页面
        3.元素定位+元素操作,输入用户名和密码,点击登录
        4.通过获取页面内容得到实际结果,进行断言
        :return:
        """

        from selenium import webdriver

        #1.打开浏览器
        driver = webdriver.Chrome()
        #设置隐性等待 等待的时间就可以放在config中,直接参数调用
        ##方法一:放在yaml中
        wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"]
        ##方法二、放在config.py中
        #wait_time = Wait_time
        driver.implicitly_wait(wait_time)

        #2.访问登录页面
        url = "http://120.78.128.25:8765/Index/login.html"
        driver.get(url)

        #3.元素定位+元素操作,输入用户名和密码,点击登录
        driver.find_element_by_name("phone").send_keys(eval(test_info["data"])["username"])
        driver.find_element_by_name("password").send_keys(eval(test_info["data"])["password"])
        driver.find_element_by_class_name("btn-special").click()

        #4.通过获取页面内容得到实际结果,进行断言
        #实际结果是在页面上的提示,再次进行定位
        actual_result = driver.find_element_by_class_name("form-error-info").text
        expected_result = test_info["expected_result"]
        #断言
        self.assertTrue(actual_result == expected_result)

通过pytest用例筛选运行error用例,读取web_excel.xlsx中的2条用例(一条通过,一条不通过),run,py代码如下:

"运行测试用例"
import pytest
import datetime
ts = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")

if __name__ == '__main__':
    pytest.main(["--html={}report.html".format(ts), "-m error"])

用unittest框架(使用筛选用例)的数据驱动,运行通过。

 

下面用pytest的数据驱动完成测试:

pytest数据驱动的语法:

① 在用例的方法上添加:@pytest.mark.parametrize("test_info",data)      data表示 列表表示的数据

② 用例方法中添加参数test_info

注:pytest中,类上面不需要加任何东西(因为它可能没有类)

       pytest中,parametrize中的第一个参数“test_info” 跟函数中的参数名称必须是一致的------->(def test_login_error(self,test_info):)

完成上面的操作后,还有需要跟unittest区分的是:不能继承unittest.TestCase,断言就不能用self.assertTrue了

 

代码实现如下:

"""登录功能的测试用例"""

import pytest
from middware.handler import HandlerMiddle
from config.config import Wait_time

data = HandlerMiddle.excel.read_data("login")

@pytest.mark.login
class TestLogin():
    """登录功能的测试类"""
    @pytest.mark.smoke
    @pytest.mark.error
    @pytest.mark.parametrize("test_info",data)
    def test_login_error(self,test_info):
        """登录失败测试步骤
        1.打开浏览器
        2.访问登录页面
        3.元素定位+元素操作,输入用户名和密码,点击登录
        4.通过获取页面内容得到实际结果,进行断言
        :return:
        """

        from selenium import webdriver

        #1.打开浏览器
        driver = webdriver.Chrome()
        #设置隐性等待 等待的时间就可以放在config中,直接参数调用
        ##方法一:放在yaml中
        wait_time = HandlerMiddle.yaml_data["selenium"]["wait_time"]
        ##方法二、放在config.py中
        #wait_time = Wait_time
        driver.implicitly_wait(wait_time)

        #2.访问登录页面
        url = "http://120.78.128.25:8765/Index/login.html"
        driver.get(url)

        #3.元素定位+元素操作,输入用户名和密码,点击登录
        driver.find_element_by_name("phone").send_keys(eval(test_info["data"])["username"]) #定位输入手机号为空
        driver.find_element_by_name("password").send_keys(eval(test_info["data"])["password"])#定位输入的密码为空
        driver.find_element_by_class_name("btn-special").click()

        #4.通过获取页面内容得到实际结果,进行断言
        #实际结果是在页面上的提示,再次进行定位
        actual_result = driver.find_element_by_class_name("form-error-info").text
        expected_result = test_info["expected_result"]
        

     #断言 assert actual_result == expected_result

运行上面的run.py,测试通过。

 

数据驱动注意事项:

①在使用@pytest.mark.parametrize("test_info",data)做数据驱动时,pytest和unittest不兼容,即,如果想使用pytest的数据驱动,就不能继承unittest.TestCase,并修改断言

②如果用unittest写用例,就需要用 unittest 的数据驱动。(类 继承unittest.TestCase;添加ddt

 

总结来说:pytest不跟unittest兼容的是:数据驱动parametrize,测试夹具fixture,hook

只要用上面的三个,pytest和unittest 就是不兼容。