UI自动化 unittest单元测试框架(1)

一、测试范围

表单的错误提示信息验证

产品的业务逻辑

页面的各种交互(选项、悬浮)

二、金字塔模型:

UI层:可以理解为功能测试;

service:接口测试(API);

Unit(单元测试)。

 

在Python中,单元测试框架主要是unittest。单元测试是最基本也是最底层的测试类型,单元测试应用于最基本的软件代码,如类,函数、方法等,单元测试通过可执行的断言检查被测单元的输出是否满足预期结果。在测试金字塔的理论上来说,越往下的测试投入资源越高,得到的回报率越大。

 

unittest属于标准库,只要安装了Python解释器后就可以直接导入使用了import unittest

 

三、步骤:

初始化 (获取浏览器驱动对象driver,打开网页、最大化浏览器、隐式等待)

测试 步骤

断言 

清理(关闭浏览器)

   

四、单元测试框架包括

测试用例(TestCase)

测试固件初始化setUp(),清理tearDown()

测试套件(TestSuite ):组织测试用例。在一个测试套件里面可以包含很多的测试用例,可以把它理解为一个容器。测试用例的集合。

测试执行(TestRunner):测试执行指的是针对测试套件或者是测试用例进行执行的过程

测试报告(TestReport):所有的测试测试用例执行完成后输出的汇总结果报告信息

 

五、断言:

让程序代替人为判断测试程序执行结果是否符合预期结果的过程。每个自动化测试用例必须得有断言,断言本质上其实就是两个对象的比较。

1.assert为python自带断言方法:

复制代码
 1 import unittest
 2 from selenium import  webdriver
 3 
 4 class BaiDuTest(unittest.TestCase):
 5     def setUp(self) -> None:
 6         self.driver=webdriver.Chrome()
 7         self.driver.maximize_window()
 8         self.driver.get("http://www.baidu.com")
 9         self.driver.implicitly_wait(30)
10 
11 
12     def test_baidu_title(self):
13         '''验证百度首页的title信息'''
14         assert self.driver.title=="百度一下,你就知道"
15 
16 if __name__ == '__main__':
17     unittest.main()
View Code
复制代码

在字符串中,两个对象的比较主要是通过:  is , in包含 , ==相等 的方式里进行的。

 测试用例以test_开头

 

2.unittest框架中的断言方法:

 

复制代码
 1 import time
 2 import unittest
 3 import setuptools.dist
 4 from selenium import webdriver
 5 
 6 class SinaTest(unittest.TestCase):
 7     def setUp(self) -> None:
 8         self.driver=webdriver.Chrome()
 9         self.driver.maximize_window()
10         self.driver.get("http://mail.sina.com.cn/")
11         self.driver.implicitly_wait(30)
12 
13     def tearDown(self) -> None:
14         self.driver.quit()
15 
16     def test_login_email_format(self):
17         '''登录:验证账户格式不规范的错误提示信息'''
18         self.driver.find_element_by_id("freename").send_keys("saffg ")
19         self.driver.find_element_by_id("freepassword").send_keys(" rwerg")
20         self.driver.find_element_by_class_name("loginBtn").click()
21         time.sleep(3)
22         divTest=self.driver.find_element_by_xpath("/html/body/div[3]/div/div[2]/div/div/div[4]/div[1]/div[1]/div[1]/span[1]")
23         '''assertEqual比较两个对象是否相等,=='''
24         self.assertEqual(divTest.text,"您输入的邮箱名格式不正确")
25         '''assertIn比较一个对象是否包含另外一个对象,in'''
26         self.assertIn(divTest.text,"正确")
27 
28     def test_login_isButton(self):
29         '''验证按钮是否被勾选'''
30         divTest=self.driver.find_element_by_id("store1")
31         # divTest.click()
32         time.sleep(2)
33         '''针对bool的类型验证assertTrue'''
34         self.assertTrue(divTest.is_selected())
35         '''针对bool的类型验证assertFlase'''
36         self.assertFalse(divTest.is_selected())
37 
38 
39 if __name__ == '__main__':
40     unittest.main()
View Code
复制代码

(继承unittest下的TestCase类)

self.assertEqual(A,B)   

判断A B两个对象是否相等(类似于字符串的==)。不仅内容相同并且还要类型相同

 (获取文本框的内容和“    ”做比较)

 ② self.assertIn(a,b)

判断b是否包含a

assertTrue验证是否为True:如果是True则通过,如果是Flase则不通过

assertFlase验证是否为假:如果是Flase则通过,如果是True则不通过

 

 

六、测试固件:

在unittest单元测试框架中,测试固件用于处理初始化的操作,例如对百度的搜索进行操作之前,首先需要打开浏览器并且进入到百度首页;测试结束后,需要关闭浏览器。测试固件提供了两种执行形式,一种是每执行一个测试用例,测试固件都会被执行一次;另外一种是不管有多少个测试用例,测试固件只执行一次。

1、测试固件每次均执行

setUp和tearDown

2、测试固件只执行一次

类测试固件:setUpClass和tearDownClass,指的是不管一个测试类里面有多少个测试用例(方法),测试固件只执行一次。需要在方法上面加装饰器@classmethod.

优点:节约了时间。

缺点:执行完一个测试用例后,需要回归到页面的初始化。

(建议使用测试固件setUp和tearDown每次都会打开和关闭浏览器,使得自动化测试用例之间没有关联性,避免一个测试用例执行失败是由上一个测试用例导致。)

 

 

 

六、编写测试用例注意事项

回答写了多少个自动化测试用例: 4-500

1、在一个测试类里面,每一个测试方法都是以test开头的!!!test不能是中间或者尾部,必须是开头,建议test_。

2、每一个测试用例方法都应该有注释信息,这样在测试报告就会显示具体的测试点的检查点

3、在自动化测试中,每个测试用例都必须得有断言,无断言的自动化测试用例是无效的

4、最好一个测试用例方法对应一个业务测试点,不要多个业务检查点写一个测试用例

5、如果涉及到业务逻辑的处理,最好把业务逻辑的处理方法放在断言前面,这样做的目的是不要因为业务逻辑执行错误导致断言也是失败

6、测试用例名称最好规范,有约束

7、是否先写自动化测试的测试代码,在使用自动化测试方式写,本人觉得没必要,毕竟能够做自动化测试的都具备了功能测试的基本水平,所以没必要把一个业务的检查点写多次,浪费时间和人力成本。

 

七、自动化测试流程

1、先梳理哪些模块可以做自动化测试

2、梳理完成后,和相关的人(领导)建议核对下计划以及梳理的结果

3、编写代码实现梳理的测试模块

4、编写完成后,和相关的人进行评审代码(测试场景是否考虑周全,测试断言是否合理,代码编写的是否合理)

5、编写完成后,整合到Jekins持续集成平台

6、下个迭代的时候,直接可以应用于产品的回归测试

 

八、TestCase测试用例执行顺序详解

在unittest中,测试点的执行顺序是依据ascii码来执行的,也就是说根据ASCII码的顺序加载,数字与字母的顺序为:0-9,A-Z,a-z,所以以A开头的测试用例方法会优先执行,以a开头后执行。也就是根据数字的大小从小到大执行的,切记数字的大小值的是不包含test,指的是test后面的测试点的数字大小。

在自动化测试用例中,编写的测试用例不需要刻意的进行排序,让测试框架内部框架按照它的排序规则去执行。

切记:编写的每一个自动化测试用例都必须是独立的,和其他的测试用例之间没有任何的依赖性。

技巧:在某个测试用例的标题上右键执行,意思是只执行这个测试用例。在类上右键,执行整个类。

 

九、执行TestSuite测试套件

UnitTest的测试框架中提供了很丰富的测试套件,所谓测试套件其实我们可以把它理解为测试用例的集合,或者可以说理解为一个容器,在这个容器里面可以存放很多的测试用例。

TestLoader类:用来加载TestCase到TestSuite中,即满足条件的测试用例,并把测试用例封装成测试套件(suite)。

分类执行

①按测试类执行

  按测试类执行,可以理解为在测试套件中,我们按测试类的方式来进行执行,那么也就不需要在乎一个测试类里面有多少测试用例,我们是以测试类为单位来进行执行,测试类里面有多少的测试用例,我们都会进行执行

②按模块执行

 

加载所有的测试模块(重点掌握)

(discover方法必须掌握 面试必问!!!!两个参数的意思!!)

方法:

使用unittest.TestLoader类,通过该类下面的discover()方法自动搜索指定目录指定开头的.py文件,并将查找到的测试用例组装到测试套件(suite)。

加载所有测试模块到测试套件后,搭配run方法,执行测试套件(所有的测试用例)

两个参数:

star_dir:测试模块的路径(指定目录)

pattern:指定测试模块名通过*正则的方式,“test_*.py”表示以test_开头的所有模块。所以我们命名测试模块的时候注意格式:test_xxx.py)

 

执行方法

TextTestRunner:

执行测试套件的方法。

调用类TextTestRunner下的run方法,TextTestRunner后面要带括号表示类实例化。

unittest.TextTestRunner().run(suite)也就是相当于

runner=unittest.TextTestRunner() 

runner.run(suite)

一行代码更简洁。

 

十、参数化:

参数化:
相同的测试步骤不同的测试数据,那么这样的测试场景我们就可以使用参数化的解决思路来解决。
也就是说使用一个测试用例的代码,执行多个测试场景.

参数化本质:
针对测试数据进行循环,每次循环的时候对列表中的元素的值一一赋值的过程

Parameterized 是 Python 的一个参数化库,同时支持 unittest、Nose 和 pytest 单元测试
框架

cmd中安装pip3 install parameterized

 参数化:根据需求动态获取参数并引用的过程。解决相同操作步骤、不同测试数据的问题。

导入包 from parameterized import parameterized;

修饰测试函数@parameterized.expand(列表类型)

在测试函数中使用变量接收传递过来的值,变量的数量必须和数据值的个数相同。

 

十一、测试报告

执行了测试套件可以看到测试的结果,但是如果希望有一个系统的 完整的测试报告,就需要使用到HTMLTestRunner

11.1 准备工作

1、unittest生成测试报告需要使用到第三方的库HTMLTestRunner,把该库放在Python安装目录下的lib目录下。

 

2、建report包:用来放测试报告

复制代码
 1 import os
 2 import unittest
 3 import HTMLTestRunner
 4 import time
 5 
 6 def getSuite():
 7     '''获取当前目录下所有需要执行的测试模块'''
 8     suite=unittest.TestLoader().discover(
 9         start_dir=os.path.dirname(__file__),
10         pattern="test_*.py")
11     return suite
12 
13 def getNowTime():
14     '''获取当前时间,给测试报告命名的时候加上时间,用来区分文件'''
15     return  time.strftime("%Y-%m-%d %H-%M-%S",time.localtime())
16 
17 def main():
18     filename=os.path.join(os.path.dirname(__file__),"report",getNowTime()+"report.html")  #定义文件(路径拼接加文件命名)
19     fp=open(filename,"wb")        #二进制写入
20     runner=HTMLTestRunner.HTMLTestRunner(
21         stream=fp,
22         title="UI自动化测试报告",
23         description="测试报告"
24     )                           #HTMLTestRunner类实例化 对报告进行描述
25     runner.run(getSuite())      #HTMLTestRunner类下的run方法执行 (运行给定测试套件)
26 
27 if __name__ == '__main__':
28     main()
View Code
复制代码

11.2步骤:

用到了TestLoader()类的discover()方法,获取当前目录下所有需要执行的测试模块到测试固件;

获取当前时间,用来给测试报告命名;(注意时间格式 命名不能有引号)

HTMLTestRunner类实例化,进行参数赋值,定义测试报告;

实例化后就可以使用run方法来执行测试套件

把执行的测试套件结果放入测试报告。

查看测试报告:

 (测试用例写注释,测试报告中就会显示)

 

posted @   jia---  阅读(145)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示