1. unittest框架解析
Java Junit单元测试框架(白盒测试) unittest框架:黑盒测试,UI界面 unittest单元测试直接提供了创建测试用例,测试套件以及批量执行的方案,unittest在安装在python以后就直接自带了,直接import unittest就可以使用了。 作为单元测试的框架,unittest也可以对程序最小模块的一种敏捷化的测试。在自动化测试中,我们虽然不需要做白盒测试,但是必须需要知道所使用语言的单元测试框架。利用单元测试框架,创建一个类,该类继承unittest的TestCase,这样可以把case看成是一个最小单元,由测试容器组织起来,到时候直接执行,同时引入测试报告。
1.1.unittest的测试固件
测试固件: SetUp():初始化 TearDown():UI功能测试后的清理工作; TestCase:每一个测试用例,继承自unittest test_开头 测试套件:把不同的测试用例组合在一起; HTMLReport:测试报告
1.2 unittest框架的使用
self:代表的是类的实例,在方法的一个参数,在方法的第一个参数,调用方法的时候可以不传参数; 定义全局变量self.变量名
from selenium import webdriver
import unittest
import time
from selenium. common. exceptions import NoAlertPresentException
from selenium. common. exceptions import NoSuchElementException
class Baidu1 ( unittest. TestCase) :
def setUp ( self) :
print ( "--------setUp()---------" )
self. driver = webdriver. Chrome( ) ;
self. url = "https://www.baidu.com/"
self. driver. maximize_window( )
time. sleep( 3 )
def tearDown ( self) :
print ( "---------tearDown()-------" )
self. driver. quit( )
def test_hao ( self) :
driver = self. driver;
driver. get( self. url)
time. sleep( 3 )
driver. find_element_by_link_text( "hao123" ) . click( )
time. sleep( 6 )
def test_baiduSerch ( self) :
driver = self. driver
driver. get( self. url)
time. sleep( 3 )
driver. find_element_by_id( "kw" ) . send_keys( "山河令" )
driver. find_element_by_id( "su" ) . click( )
time. sleep( 6 )
if __name__ == "__main__" :
unittest. main( verbosity= 1 )
verbosity是一个选项,表示测试结果的信息复杂度,有三个值: 0(静默模式):只能获得总的测试用例数和总的结果,比如说总共100个,失败20个,成功80个; 1(默认模式)非常类似静默模式只是在每个从隔壁发过成功的前面有个“.”,每个失败的测试用例前面有个“F” 2(详情模式):测试结果会显示每个测试用例的所有相关的信息。
1.3 TestSuite(测试套件)
1.3.1 addTest
当有多个或者几百个测试用例的时候,我们就需要一个测试容器(测试套件),把测试用例放到该容器中执行,unittest模块中提供了TestSuit类生成测试套件,使用该类的构造函数可以生成一个测试套件的实例,该类提供了addTest把每个测试用例加入到测试套件中。
import unittest
from src202107 import testbadu1
from src202107 import testbadu2
def createsuite ( ) :
suite = unittest. TestSuite( )
suite. addTest( testbadu1. Baidu1( "test_hao" ) )
suite. addTest( testbadu1. Baidu1( "test_baiduSerch" ) )
suite. addTest( testbadu2. Baidu2( "test_hao" ) )
suite. addTest( testbadu2. Baidu2( "test_baiduSerch" ) )
return suite
if __name__ == "__main__" :
suite = createsuite( )
runner = unittest. TextTestRunner( verbosity= 1 )
runner. run( suite)
1.3.2 makeSuit()
在unittest框架中提供了makeSuit()的方法,makeSuit可以实现把测试用例类内的所有测试的case组成的测试套件的TestSuit,unittest调用makeSuit的时候,只需要把测试类的名称传入即可。
import unittest
from src202107 import testbadu1
from src202107 import testbadu2
def createsuite ( ) :
suite = unittest. TestSuite( )
suite. addTest( unittest. makeSuite( testbadu1. Baidu1) )
suite. addTest( unittest. makeSuite( testbadu1. Baidu1) )
return suite
if __name__ == "__main__" :
suite = createsuite( )
runner = unittest. TextTestRunner( verbosity= 0 )
runner. run( suite)
1.3.3 testLoader()的应用
TestLoader 用于创建类和模块的测试套件,一般的情况下,使用TestLoader().loadTestsFromTestCase(TestClass)来加载测试类。
import unittest
from src202107 import testbadu1
from src202107 import testbadu2
def createsuite ( ) :
suite1 = unittest. TestLoader( ) . loadTestsFromTestCase( testbadu1. Baidu1)
suite2 = unittest. TestLoader( ) . loadTestsFromTestCase( testbadu2. Baidu2)
suite = unittest. TestSuite( [ suite1, suite2] )
return suite
if __name__ == "__main__" :
suite = createsuite( )
runner = unittest. TextTestRunner( verbosity= 2 )
runner. run( suite)
1.3.4 discover()的应用
discover是通过递归的方式到其子目录中指定的目录开始,找到所有测试模块并返回一个包含他们对象的TestSuite,然后进行加载与模式匹配唯一的测试文件,discover的参数分别为: discover(dir,pattern,top_level_dir=None)
import unittest
from src202107 import testbadu1
from src202107 import testbadu2
def createsuite ( ) :
discover = unittest. defaultTestLoader. discover( "../src202107" , pattern= "testbadu*.py" , top_level_dir= None )
print ( discover)
return discover
if __name__ == "__main__" :
suite = createsuite( )
runner = unittest. TextTestRunner( verbosity= 1 )
runner. run( suite)
2.测试用例的执行顺序
unittest 框架默认加载测试用例的顺序是根据ASCII 码的顺序,数字与字母的顺序为: 0~9,A-Z,a-z 。 TestAdd 类会优先于TestBdd 类被发现, test_aaa() 方法会优先于test_ccc() 被执行。对于测试目录与测试文件来说, unittest 框架同样是按照这个规则来加载测试用例。 addTest()方法是按照增加顺序来执行。
3.忽略测试用例
忽略测试用例的执行:@unittest.skip(“skipping”)
@unittest. skip ( "skipping" )
def test_hao ( self) :
driver = self. driver;
driver. get( self. url)
time. sleep( 3 )
driver. find_element_by_link_text( "hao123" ) . click( )
time. sleep( 6 )
4. unittest断言
自动化的测试中, 对于每个单独的case来说,一个case的执行结果中, 必然会有期望结果与实际结果, 来判断该case是通过还是失败, 在unittest 的库中提供了大量的实用方法来检查预期值与实际值, 来验证case的结果, 一般来说, 检查条件大体分为等价性, 逻辑比较以及其他, 如果给定的断言通过, 测试会继续执行到下一行的代码, 如果断言失败, 对应的case测试会立即停止或者生成错误信息( 一般打印错误信息即可) ,但是不要影响其他 的case执行。 unittest 的单元测试库提供了标准的xUnit 断言方法。下面是一些常用的断言:
断言方法 断言描述 assertEqual(arg1, arg2, msg=None ) 验证arg1=arg2,不等则fail assertNotEqual(arg1, arg2, msg=None) 验证arg1 != arg2, 相等则fail assertTrue(expr, msg=None) 验证expr是true,如果为false,则fai assertFalse(expr,msg=None) 验证expr是false,如果为true,则fail assertIs(arg1, arg2, msg=None) 验证arg1、arg2是同一个对象,不是则fail assertIsNot(arg1, arg2, msg=None) 验证arg1、arg2不是同一个对象,是则fail
def test_hao ( self) :
driver = self. driver;
driver. get( self. url)
time. sleep( 3 )
print ( driver. title)
self. assertNotEqual( driver. title, "百度一下,你就知道" , msg= "不相等!" )
driver. find_element_by_link_text( "hao123" ) . click( )
time. sleep( 6 )
def test_baiduSerch ( self) :
driver = self. driver
driver. get( self. url)
time. sleep( 3 )
driver. find_element_by_id( "kw" ) . send_keys( "你好,火焰蓝" )
driver. find_element_by_id( "su" ) . click( )
self. assertFalse( "hello" == "heeell" , msg= "not equal " )
time. sleep( 6 )
5. HTML 报告的生成
import unittest
import sys, os
import time, HTMLTestRunner
from src202107 import testbadu1
from src202107 import testbadu2
def createsuite ( ) :
discover = unittest. defaultTestLoader. discover( "../src202107" , pattern= "testbadu*.py" , top_level_dir= None )
print ( discover)
return discover
if __name__ == "__main__" :
curpath = sys. path[ 0 ]
print ( sys. path)
print ( sys. path[ 0 ] )
if not os. path. exists( curpath+ '/resultreport' ) :
os. makedirs( curpath+ '/resultreport' )
now = time. strftime( "%Y-%m-%d-%H %M %S" , time. localtime( time. time( ) ) )
print ( time. time( ) )
print ( time. localtime( time. time( ) ) )
filename = curpath+ '/resultreport' + now + 'resultreport.html'
with open ( filename, 'wb' ) as fp:
runner = HTMLTestRunner. HTMLTestRunner( stream= fp, title= u"测试报告" ,
description= u"用例执行情况" , verbosity= 2 )
suite = createsuite( )
runner. run( suite)
6.异常捕捉和错误截图
BUG的要素:测试版本,测试环境,测试步骤,测试数据。测试的预期结果,测试的实际结果,其他(日志,错误截图) 需要注意以下问题
错误截图的的存储位置; 解决重复命名的问题; 截图
from selenium import webdriver
import unittest
import time
import os
import re
from selenium. common. exceptions import NoAlertPresentException
from selenium. common. exceptions import NoSuchElementException
class Baidu1 ( unittest. TestCase) :
def setUp ( self) :
self. driver = webdriver. Chrome( )
self. driver. implicitly_wait( 30 )
self. base_url = "http://www.baidu.com/"
self. verificationErrors= [ ]
self. accept_next_alert = True
def tearDown ( self) :
self. driver. quit( )
self. assertEqual( [ ] , self. verificationErrors)
def test_baidu ( self) :
driver = self. driver
driver. get( self. base_url)
driver. maximize_window( )
time. sleep( 6 )
print ( driver. title)
try :
self. assertEqual( u"dddd百度一下,我就知道" , driver. title)
except :
self. saveScreenShot( driver, "hao.png" )
time. sleep( 5 )
def saveScreenShot ( self, driver, file_name) :
if not os. path. exists( "./image" ) :
os. makedirs( "./image" )
now = time. strftime( "%Y%m%d-%H%M%S" , time. localtime( time. time( ) ) )
driver. get_screenshot_as_file( "./image/" + now+ "-" + file_name)
time. sleep( 3 )
if __name__ == "__main__" :
unittest. main( )
注意:调用一个方法,用self.方法名,方法传参数的时候确实不用传第一个参数self.