Bootstrap

从零开始编写Web自动化测试脚本(八)--unittest&断言

第一章 Selenium+WebDriver环境搭建
第二章 Selenium定位方式
第三章 元素常用属性
第四章 自动化中的三种等待
第五章 自动化浏览器设置及句柄、窗口切换操作
第六章 鼠标、键盘操作
第七章 javascript在自动化中的应用
第八章 unittest&断言
第九章 ddt数据驱动
第十章 测试框架搭建过程Python+Selenium+BeautifulReport



一、unittest测试框架的介绍与使用

1、unittest框架及原理

python中的unittest框架,它是python自带的一套测试框架,学习起来也相对较容易,unittest框架最核心的四个概念:
①TestCase:测试用例
②TestFixure:测试夹具,用于测试用例环境的搭建和销毁 --测试准备 ③TestSuite:测试套件,用来把需要一起执行的测试用例集中放到一块执行,相当于一个篮子。 我们可以使用TestLoader来加载测试用例到测试套件中。
④TestRunner:就是用来执行测试用例的,并且可以生成相应的测试报告

2、unittest之TestCase

TestCase:就是我们的测试用例,unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的实例就是一个测试用例;
unittest中测试用例方法都是以test开头的,否则不被unittest识别,执行顺序根据(0-9,A-Z,a-z)

3、TestCase测试用例

编写测试用例前,我们需要建一个测试类继承unittest里面的TestCase类,继承这个类之后我们才是真正的使用unittest框架去写测试用例,编写测试用例的步骤如下:
①导入unittest模块
②创建一个测试类,并继承unittest.TestCase()
③定义测试方法,方法名必须以test开头
④调用unittest.main()方法来运行测试用例,unittest.main()方法会搜索该模块下所有以test开头的测试用例方法,并自动执行
⑤每一个用例执行的结果的标识,成功是 .,失败是 F,出错是E

例如登录的测试案例一,编写登录流程的代码,并封装为函数

import time
from selenium import webdriver
from selenium.webdriver.common.by import By

def login_in(user, pwd):
    driver = webdriver.Chrome()
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()
    time.sleep(3)
    driver.quit()

login_in("[email protected]", "11111111")

例如登录的测试案例二,新建测试python文件,对登录进行用例设计

用例编号用户名密码预期结果检查点
test_login_001[email protected]11111111登录成功浏览器title等于QQ邮箱
test_login_00212345678911111111登录失败提示信息:账户不存在
test_login_003[email protected]22222222登录失败提示信息:密码错误
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest

def login_in(user, pwd):
    driver = webdriver.Chrome()
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()
    time.sleep(3)
    driver.quit()

class Test_login(unittest.TestCase):
    # 账户密码正确,登录成功
    def test_login_001(self):
        login_in("[email protected]", "11111111")

    # 账户错误,密码错误,登录失败
    def test_login_002(self):
        login_in("123456789", "11111111")

    # 账户正确,密码错误,登录失败
    def test_login_003(self):
        login_in("[email protected]", "22222222")

if __name__ == '__main__':
    unittest.main

4、unittest之TestFixure

TestFixure:测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建 (SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取 token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一 条用例的测试结果。
unittest的测试夹具有两种使用方式,一种是以测试方法为维度的setUp()和tearDown(),一种是以测试类为维度的setUpClass()和tearDownClass(),对于测试类维度的方法,必须要使用装饰器@classmethod

例如登录的测试案例三,执行3次登录,一次登录成功,两次登录失败,要求只打开一次浏览器和关闭一次浏览器; 在每次执行用例前输出‘开始执行用例’,执行用例完成后输出‘用例执行完毕’
①打开浏览器、关闭浏览器只做一次,放到setUpClass()和tearDownClass()中。需要使用 @classmethod装饰器
②每次执行用例前输出‘开始执行用例’,执行用例完成后输出‘用例执行完毕’,将输出的文本放在 setUp()和tearDown()中

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest

def login_in(driver, user, pwd):
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()

class Test_login(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        global driver
        driver = webdriver.Chrome()
        print("打开浏览器")

    @classmethod
    def tearDownClass(cls) -> None:
        time.sleep(3)
        driver.quit()
        print("关闭浏览器")

    def setUp(self) -> None:
        print("开始执行用例")

    def tearDown(self) -> None:
        print("用例执行完毕")

    # 账户密码正确,登录成功
    def test_login_001(self):
        login_in(driver, "[email protected]", "11111111")
        print("test_login_001")

    # 账户错误,密码错误,登录失败
    def test_login_002(self):
        login_in(driver, "123456789", "11111111")
        print("test_login_002")

    # 账户正确,密码错误,登录失败
    def test_login_003(self):
        login_in(driver, "[email protected]", "22222222")
        print("test_login_003")

if __name__ == '__main__':
    unittest.main

5、unittest之TestSuite

unittest.TestSuite()类来表示一个测试用例集,把需要执行的用例类或模块存到一起,操作如下:
①创建测试集:suite=unittest.TestSuite()
②测试集中添加指定的测试用例:
方式一:添加单个测试用例方法
addTest(类名(方法名)):
方式二:添加多个测试用例方法,方法名存在一个列表
addTests([类名(方法名1),类名(方法名2)…]):
方式三:添加所有测试用例
unittest.TestLoader()
loadTestsFromTestCase(测试类名):添加一个测试类
loadTestsFromModule(模块名):添加一个模块
③执行测试集
①创建执行器:runner= unittest.TextTestRunner() 或者 runner=HTMLTestRunner()
②执行测试集:runner.run(suite)

例如登录的测试案例四:
需求1:将登录成功的用例放到测试套件中执行
只会执行登录成功的测试用例

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest

def login_in(driver, user, pwd):
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()

class Test_login(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        global driver
        driver = webdriver.Chrome()
        print("打开浏览器")

    @classmethod
    def tearDownClass(cls) -> None:
        time.sleep(3)
        driver.quit()
        print("关闭浏览器")

    def setUp(self) -> None:
        print("开始执行用例")

    def tearDown(self) -> None:
        print("用例执行完毕")

    # 账户密码正确,登录成功
    def test_login_001(self):
        login_in(driver, "[email protected]", "11111111")
        print("test_login_001")

    # 账户错误,密码错误,登录失败
    def test_login_002(self):
        login_in(driver, "123456789", "11111111")
        print("test_login_002")

    # 账户正确,密码错误,登录失败
    def test_login_003(self):
        login_in(driver, "[email protected]", "22222222")
        print("test_login_003")

if __name__ == '__main__':
    # 1、创建测试套件
    suite = unittest.TestSuite()
    # 2、将测试用例加载到测试套件中
    case1 = Test_login("test_login_001")
    suite.addTest(case1)
    # 3、执行测试套件,生成文本报告
    runner = unittest.TextTestRunner()
    runner.run(suite)

需求2:将登录成功和登录失败的1条用例放到测试套件中执行
只会执行加入的2条用例

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest

def login_in(driver, user, pwd):
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()

class Test_login(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        global driver
        driver = webdriver.Chrome()
        print("打开浏览器")

    @classmethod
    def tearDownClass(cls) -> None:
        time.sleep(3)
        driver.quit()
        print("关闭浏览器")

    def setUp(self) -> None:
        print("开始执行用例")

    def tearDown(self) -> None:
        print("用例执行完毕")

    # 账户密码正确,登录成功
    def test_login_001(self):
        login_in(driver, "[email protected]", "11111111")
        print("test_login_001")

    # 账户错误,密码错误,登录失败
    def test_login_002(self):
        login_in(driver, "123456789", "11111111")
        print("test_login_002")

    # 账户正确,密码错误,登录失败
    def test_login_003(self):
        login_in(driver, "[email protected]", "22222222")
        print("test_login_003")

if __name__ == '__main__':
    # 1、创建测试套件
    suite = unittest.TestSuite()
    # 2、将测试用例1加载到测试套件中
    case1 = Test_login("test_login_001")
    # 将测试用例2加载到测试套件中
    case2 = Test_login("test_login_002")
    suite.addTests([case1, case2])
    # 3、执行测试套件,生成文本报告
    runner = unittest.TextTestRunner()
    runner.run(suite)

需求3:将所有用例放到测试套件中执行
unittest.TestLoader:负责根据各种标准加载测试并将他们包装在TestSuite中

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest

def login_in(driver, user, pwd):
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()

class Test_login(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        global driver
        driver = webdriver.Chrome()
        print("打开浏览器")

    @classmethod
    def tearDownClass(cls) -> None:
        time.sleep(3)
        driver.quit()
        print("关闭浏览器")

    def setUp(self) -> None:
        print("开始执行用例")

    def tearDown(self) -> None:
        print("用例执行完毕")

    # 账户密码正确,登录成功
    def test_login_001(self):
        login_in(driver, "[email protected]", "11111111")
        print("test_login_001")

    # 账户错误,密码错误,登录失败
    def test_login_002(self):
        login_in(driver, "123456789", "11111111")
        print("test_login_002")

    # 账户正确,密码错误,登录失败
    def test_login_003(self):
        login_in(driver, "[email protected]", "22222222")
        print("test_login_003")

if __name__ == '__main__':
    # 1、创建测试套件
    suite = unittest.TestSuite()
    # 2、添加一个测试用例类中的所有用例
    loader = unittest.TestLoader()
    suite.addTest(loader.loadTestsFromTestCase(Test_login))
    # 3、执行测试套件,生成文本报告
    runner = unittest.TextTestRunner()
    runner.run(suite)

二、unittest的断言

unittest框架中提供了一个自带的断言方式,主要有以下几种:

方法检查
assertEqual(a, b, msg=None)a == b
assertNotEqual(a, b)a != b
assertTrue(x)bool(x) is True
assertFalse(x)bool(x) is False
assertIs(a, b)a is b
assertIsNot(a, b)a is not b
assertIsNone(x)x is None
assertIsNotNone(x)x is not None
assertIn(a, b)a in b
assertNotIn(a, b)a not in b
assertIsInstance(a, b)isinstance(a, b)
assertNotIsInstance(a, b)not isinstance(a, b)

三、生成HTML测试报告

1、unittest之TestRunner

TestRunner顾名思义就是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式.
html格式的就是HTMLTestRunner了,HTMLTestRunner是 Python标准库的unittest框架的一个扩展,它可以生成一个直观清晰的HTML测试报告。使用的前提就是要下载HTMLTestRunner.py,下载完后放在python的安装目录下的Lib目录下即可。
text文本相对于html来说过于简陋,与控制台输出的没有什么区别,也几乎没有人使用,这里不作演示,使用方法是一样的。
参数
①报告verbosity参数可以控制执行结果的输出,0 是简单报告、1 是一般报告、2 是详细报告

import time
from selenium import webdriver
from selenium.webdriver.common.by import By
import unittest

def login_in(driver, user, pwd):
    driver.get("https://mail.qq.com")
    # 定位到登录框iframe
    iframe = driver.find_element(By.ID, "login_frame")
    # 切换进iframe
    driver.switch_to.frame(iframe)
    # 输入账号
    driver.find_element(By.ID, "u").send_keys(user)
    # 输入密码
    driver.find_element(By.ID, "p").send_keys(pwd)
    time.sleep(3)
    # 点击登录按钮即可,因为后续有安全验证,我们先忽略
    driver.find_element(By.ID, "login_button").click()

class Test_login(unittest.TestCase):

    @classmethod
    def setUpClass(cls) -> None:
        global driver
        driver = webdriver.Chrome()
        print("打开浏览器")

    @classmethod
    def tearDownClass(cls) -> None:
        time.sleep(3)
        driver.quit()
        print("关闭浏览器")

    def setUp(self) -> None:
        print("开始执行用例")

    def tearDown(self) -> None:
        print("用例执行完毕")

    # 账户密码正确,登录成功
    def test_login_001(self):
        login_in(driver, "[email protected]", "11111111")
        print("test_login_001")

    # 账户错误,密码错误,登录失败
    def test_login_002(self):
        login_in(driver, "123456789", "11111111")
        print("test_login_002")

    # 账户正确,密码错误,登录失败
    def test_login_003(self):
        login_in(driver, "[email protected]", "22222222")
        print("test_login_003")

if __name__ == '__main__':
    # 1、创建测试套件
    suite = unittest.TestSuite()
    # 2、将测试用例加载到测试套件中
    case1 = Test_login("test_login_001")
    suite.addTest(case1)
    # 3、执行测试套件,生成文本报告,2详细报告
    runner = unittest.TextTestRunner(verbosity=2)
    runner.run(suite)

②报告stream参数可以将报告输出到文件:可以用HTMLTestRunner输出html报告。注意:因为下载的HTMLTestRunner.py是针对python2写的,在Python3上使用会报错,如果想用需要修改部分代码,具体可以自己研究或百度一下。

runner = HTMLTestRunner(stream, tester, description, title) 
参数:stream--报告文件,
			tester--测试人员,
			description-报告描述信息,
			title-报告标题
if __name__ == '__main__':
    # 1、创建测试套件
    suite = unittest.TestSuite()
    # 2、添加一个测试用例类中的所有用例
    loader = unittest.TestLoader()
    suite.addTest(loader.loadTestsFromTestCase(Test_login))
    # 3、执行测试套件,生成文本报告
    runner = HTMLTestRunner(stream=open("report.html", "wb"),
                            tester="拒绝内卷的小测试",
                            description="登录功能测试报告",
                            title="自动化测试报告")
    runner.run(suite)

随手点赞一次,运气增加一份。

;