• Unittest单元测试框架全栈知识


    对一个测试的系统,开始最佳的测试就是源代码级别的测试,也就是单元测试阶段,这个过程也被成为白盒测试。单元测试是最基本也是最底层的测试类型,单元测试应用最基本的软件代码,如类,函数。方法等,单元测试通过可执行的断言检查被测单元的输出是否满足预期结果。在测试金字塔的理论上来说,越往下的测试投入资源越高,得到的回报率越大。
      1、测试金字塔模型初识

    最顶端为UI测试,中间为接口测试,最底部为单元测试。
      2、白盒测试理论
     在软件架构的层面来说,测试最核心的步骤就是在软件开发过程中。就软件本身而言,软件的行为或者功能是软件 细节实现的产物,这些最终是交付给用户的东?。所以在早期执行测试的系统有可能是一个可测试和健壮的系统, 它会带来为用户提供的功能往往是让人满意的结果。因此给予这样的?度,开始执行测试的最佳方法是来自源代码,也就是软件编写的地方以及开发人员。由于源代码是对开发人员是可?的,这样的一个测试过程我们可以称为 白盒测试。
      3、技术栈的简介
     在自动化测试过程中,编写的每一个测试用例都是需要借助单元测试框架的,那么在Python技术栈中,单元测试框架主要是unittest和Pytest,Java技术栈里面主要使用的是junit和testng。
      4、自动化测试用例的执行步骤

    设置:做一件事的前置动作,也就是初始化。
      执行:测试步骤(具体干一件事的操作步骤)。
      验证:断言,验证做一件事的结果是否正确。
      清理:后置动作。
      5、unitest是单元测试框架,使用它的注意事项:
      1)所有的测试用例都必须在test包下。
      2)每个测试模块都应该是以test_模块名称来命名 。
      3)测试类建议以Test开头。
      4)每个测试类必须继承unittest模块中的TestCase类,这样就可以直接调用里面的方法(若是不继承,就直接采用对象进行类的实例化再调用里面的方法)。
      5)在测试类里面编写的方法叫测试方法,测试方法必须是以test开头的。
      6、unittest组件

    测试用例:就是测试类里面编写的测试方法。
      测试固件:初始化和清理,使用到的方法分别是setUp()和tearDown();
      测试套件:就是测试用例的集合,在一个测试套件中可以有很多的测试用例,它的英文单词是TestSuite;
      测试执行:TestRunner,执行测试套件或者测试用例。
      测试报告:TestReport,就是执行所有测试用例后的结果信息。
      7、测试固件
      1)setUp() and tearDown():在一个测试类里面,有多少个测试用例,它就会被执行多少次。
      2)setUpClass() and tearDownClass():是类方法,不管测试类里面有多少测试用例,它只会执行一次。
      8、unittest的入门示例

    1. import unittest
    2.    from selenium.webdriver.common.by import By
    3.    from selenium.webdriver.common.action_chains import ActionChains
    4.    import time as t
    5.   
    6.    def add(a,b):
    7.    return a+b
    8.   
    9.    class TestAdd(unittest.TestCase):
    10.    def test_add_int(self):
    11.    assert add(3,5)==8

    9、百度首页测试示例(test_baidu),测试固件每次执行

    1. 1 import unittest
    2.    2 from selenium import webdriver
    3.    3 from selenium.webdriver.common.by import By
    4.    4 from selenium.webdriver.common.action_chains import ActionChains
    5.    5 from test.init import Init
    6.    6 import time as t
    7.    7
    8.    8 class TestBaidu(Init):
    9.    9 def setUp(self) -> None:
    10.   10 self.driver = webdriver.Chrome()
    11.   11 self.driver.maximize_window()
    12.   12 self.driver.get("https://www.baidu.com/")
    13.   13
    14.   14
    15.   15 def tearDown(self) -> None:
    16.   16 self.driver.quit()
    17.   17
    18.   18
    19.   19 def test_baidu_title(self):
    20.   20 '''百度首页:验证百度的title是否正确'''
    21.   21 # assert self.driver.title=="百度一下,你就知道"
    22.   22 self.assertEqual(self.driver.title, "百度一下,你就知道")
    23.   23
    24.   24
    25.   25 def test_baidu_url(self):
    26.   26 '''百度首页:验证百度的网址是否正确'''
    27.   27 # 浏览器输入网址必须为https,域名后边必须有斜杠
    28.   28 # assert self.driver.current_url=="https://www.baidu.com/"
    29.   29 self.assertEqual(self.driver.current_url, "https://www.baidu.com/")
    30.   30
    31.   31
    32.   32 def test_baidu_so(self):
    33.   33 '''百度首页:验证搜索框输入的关键字是否是接口测试'''
    34.   34 so = self.driver.find_element(By.ID, 'kw')
    35.   35 so.send_keys("接口测试")
    36.   36 # assert so.get_attribute("value")=="接口测试"
    37.   37 self.assertEqual(so.get_attribute("value"), "接口测试")
    38.   38
    39.   39
    40.   40 def test_baidu_enabled(self):
    41.   41 '''百度首页:验证搜索框是否可编辑'''
    42.   42 so = self.driver.find_element(By.ID, 'kw')
    43.   43 self.assertTrue(so.is_enabled())
    44.   44
    45.   45 def test_baidu_displayed(self):
    46.   46 '''百度首页:验证关于百度的字条是否可见'''
    47.   47 so = self.driver.find_element(By.LINK_TEXT, '关于百度')
    48.   48 self.assertTrue(so.is_displayed())
    49.   49
    50.   50 def test_baidu_setting(self):
    51.   51 '''百度首页:验证百度首页的设置的搜索设置是否打开'''
    52.   52 t.sleep(3)
    53.   53 setting=self.driver.find_element(By.XPATH,'//*[@id="s-usersetting-top"]')
    54.   54 action=ActionChains(driver=self.driver)
    55.   55 action.move_to_element(setting).perform()
    56.   56 self.driver.find_element(By.XPATH,'//*[@id="s-user-setting-menu"]/div/a[1]/span').click()
    57.   57 t.sleep(3)
    58.   58 soSet=self.driver.find_element(By.XPATH,'//*[@id="wrapper"]/div[6]/div/div/ul/li[1]')
    59.   59 # assert devText.text=="搜索设置"
    60.   60 self.assertEqual(soSet.text,"搜索设置")
    61.   61
    62.   62 if __name__ == '__main__':
    63.   63 unittest.main()

    10、使用setUpClass() and tearDownClass()类的百度首页测试,测试固件只执行一次

    1. 1 import unittest
    2.    2 from selenium import webdriver
    3.    3 from selenium.webdriver.common.by import By
    4.    4 from selenium.webdriver.common.action_chains import ActionChains
    5.    5 from test.init import Init
    6.    6 import time as t
    7.    7
    8.    8 class TestBaidu(Init):
    9.    9 class TestBaidu(Init):
    10.   10 #使用setUpClass()方法
    11.   11 @classmethod
    12.   12 def setUpClass(cls) -> None:
    13.   13 cls.driver = webdriver.Chrome()
    14.   14 cls.driver.maximize_window()
    15.   15 cls.driver.get('http://www.baidu.com')
    16.   16 cls.driver.implicitly_wait(30)
    17.   17 #使用tearDownClass()类方法
    18.   18 @classmethod
    19.   19 def tearDownClass(cls) -> None:
    20.   20 cls.driver.quit()
    21.   21
    22.   22
    23.   23 def test_baidu_title(self):
    24.   24 '''百度首页:验证百度的title是否正确'''
    25.   25 # assert self.driver.title=="百度一下,你就知道"
    26.   26 self.assertEqual(self.driver.title, "百度一下,你就知道")
    27.   27
    28.   28
    29.   29 def test_baidu_url(self):
    30.   30 '''百度首页:验证百度的网址是否正确'''
    31.   31 # 浏览器输入网址必须为https,域名后边必须有斜杠
    32.   32 # assert self.driver.current_url=="https://www.baidu.com/"
    33.   33 self.assertEqual(self.driver.current_url, "https://www.baidu.com/")
    34.   34
    35.   35
    36.   36 def test_baidu_so(self):
    37.   37 '''百度首页:验证搜索框输入的关键字是否是接口测试'''
    38.   38 so = self.driver.find_element(By.ID, 'kw')
    39.   39 so.send_keys("接口测试")
    40.   40 # assert so.get_attribute("value")=="接口测试"
    41.   41 self.assertEqual(so.get_attribute("value"), "接口测试")
    42.   42
    43.   43
    44.   44 def test_baidu_enabled(self):
    45.   45 '''百度首页:验证搜索框是否可编辑'''
    46.   46 so = self.driver.find_element(By.ID, 'kw')
    47.   47 self.assertTrue(so.is_enabled())
    48.   48
    49.   49 def test_baidu_displayed(self):
    50.   50 '''百度首页:验证关于百度的字条是否可见'''
    51.   51 so = self.driver.find_element(By.LINK_TEXT, '关于百度')
    52.   52 self.assertTrue(so.is_displayed())
    53.   53
    54.   54 def test_baidu_setting(self):
    55.   55 '''百度首页:验证百度首页的设置的搜索设置是否打开'''
    56.   56 t.sleep(3)
    57.   57 setting=self.driver.find_element(By.XPATH,'//*[@id="s-usersetting-top"]')
    58.   58 action=ActionChains(driver=self.driver)
    59.   59 action.move_to_element(setting).perform()
    60.   60 self.driver.find_element(By.XPATH,'//*[@id="s-user-setting-menu"]/div/a[1]/span').click()
    61.   61 t.sleep(3)
    62.   62 soSet=self.driver.find_element(By.XPATH,'//*[@id="wrapper"]/div[6]/div/div/ul/li[1]')
    63.   63 # assert devText.text=="搜索设置"
    64.   64 self.assertEqual(soSet.text,"搜索设置")
    65.   65
    66.   66 if __name__ == '__main__':
    67.   67 unittest.main()

    11、assert的常用方式:

    1.  assertEqual():比较的是两个对象的==关系
    2.   assertIn():比较的是两个对象的包含关系
    3.   assertIs():比较两个字符串的内存地址
    4.   assertTrue()
    5.   assertFalse()

    12、测试固件的分离
      在UI自动化测试中,所有的测试固件的部分的代码都是相同的,所以为了避免重复代码,提高效率,采用了测试固件分离的思想,使用继承的思想,把测试固件分离,这样的
      好处是只需要在一个地方维护测试固件,而不是多个地方维护。其他的测试类只需要继承测试固件就可以使用了。
      把测试固件分离到init.py里面,代码具体如下:

    1. 1 import unittest
    2.    2 from selenium import webdriver
    3.    3
    4.    4 class Init(unittest.TestCase):
    5.    5 def setUp(self) -> None:
    6.    6 self.driver=webdriver.Chrome()
    7.    7 self.driver.maximize_window()
    8.    8 self.driver.get("https://www.baidu.com/")
    9.    9
    10.   10 def tearDown(self) -> None:
    11.   11 self.driver.quit()

    在其它测试模块可中导入这个Init类,然后再继承这个类,具体代码如下:

      1. 1 import unittest
      2.    2 from selenium import webdriver
      3.    3 from selenium.webdriver.common.by import By
      4.    4 from selenium.webdriver.common.action_chains import ActionChains
      5.    5 #测试固件分离思想,导入Init类
      6.    6 from test.init import Init  
      7.    7 import time as t
      8.    8 #在测试类中继承Init类
      9.    9 class TestBaidu(Init):
      10.   10     def setUp(self) -> None:
      11.   11         self.driver=webdriver.Chrome()
      12.   12         self.driver.maximize_window()
      13.   13         self.driver.get("https://www.baidu.com/")
      14.   14
      15.   15     def tearDown(self) -> None:
      16.   16         self.driver.quit()
      17.   17
      18.   18     def test_baidu_title(self):
      19.   19         '''百度首页:验证百度的title是否正确'''
      20.   20         # assert self.driver.title=="百度一下,你就知道"
      21.   21         self.assertEqual(self.driver.title,"百度一下,你就知道")
      22.   22
      23.   23     def test_baidu_url(self):
      24.   24         '''百度首页:验证百度的网址是否正确'''
      25.   25         #浏览器输入网址必须为https,域名后边必须有斜杠
      26.   26         # assert self.driver.current_url=="https://www.baidu.com/"
      27.   27         self.assertEqual(self.driver.current_url,"https://www.baidu.com/")
      28.   28 if __name__ == '__main__':
      29.   29     unittest.main()

      13、新浪首页示例

      1. 1 import unittest
      2.    2 from selenium import webdriver
      3.    3 from selenium.webdriver.common.by import By
      4.    4 from selenium.webdriver.common.action_chains import ActionChains
      5.    5 import time as t
      6.    6
      7.    7 class TestSina(unittest.TestCase):
      8.    8 def setUp(self) -> None:
      9.    9 self.driver=webdriver.Chrome()
      10.   10 self.driver.maximize_window()
      11.   11 self.driver.get("https://mail.sina.com.cn/#")
      12.   12 self.driver.implicitly_wait(30)
      13.   13
      14.   14 def tearDown(self) -> None:
      15.   15 self.driver.quit()
      16.   16
      17.   17 def test_username_null(self):
      18.   18 '''新浪首页:验证用户名为空时,直接登录时的提示信息是否正确'''
      19.   19 self.driver.find_element(By.CLASS_NAME, "loginBtn").click()
      20.   20 devText = 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]')
      21.   21 self.assertEqual(devText.text, '请输入邮箱名')
      22.   22
      23.   23 def test_email_error(self):
      24.   24 '''新浪首页:验证用户名的格式错误时登录的提示信息是否正确'''
      25.   25 self.driver.find_element(By.ID, 'freename').send_keys("dgg")
      26.   26 self.driver.find_element(By.ID, 'freepassword').send_keys("fhsk")
      27.   27 self.driver.find_element(By.CLASS_NAME, "loginBtn").click()
      28.   28 devText = 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]')
      29.   29 self.assertEqual(devText.text, '您输入的邮箱名格式不正确')
      30.   30
      31.   31 def test_username_password_error(self):
      32.   32 '''新浪首页:验证用户名和密码错误时登录的提示信息是否正确'''
      33.   33 self.driver.find_element(By.ID, 'freename').send_keys("134467@sina.com")
      34.   34 self.driver.find_element(By.ID, 'freepassword').send_keys("fhsk")
      35.   35 self.driver.find_element(By.LINK_TEXT, "登录").click()
      36.   36 t.sleep(5)
      37.   37 devText = 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]')
      38.   38 t.sleep(3)
      39.   39 self.assertEqual(devText.text, '登录名或密码错误')
      40.   40
      41.   41 if __name__ == '__main__':
      42.   42 unittest.main()

      14、参数化
        当一个测试场景,它的测试步骤相同,测试数据不一样的时候,那么就可以使用参数化的思想来解决。
        在unittest测试框架中,参数化需要借助第三方的库parameterized,先使用命令pip install parameterized安装 parameterized库,再具体应用参数化思想,代码如下:

      1. 1 import unittest
      2.    2 from selenium import webdriver
      3.    3 from selenium.webdriver.common.by import By
      4.    4 from selenium.webdriver.common.action_chains import ActionChains
      5.    5 from parameterized import parameterized,param
      6.    6 import time as t
      7.    7
      8.    8 class TestSina(unittest.TestCase):
      9.    9 def setUp(self) -> None:
      10.   10 self.driver=webdriver.Chrome()
      11.   11 self.driver.maximize_window()
      12.   12 self.driver.get("https://mail.sina.com.cn/#")
      13.   13 self.driver.implicitly_wait(30)
      14.   14
      15.   15 def tearDown(self) -> None:
      16.   16 self.driver.quit()
      17.   17
      18.   18 @parameterized.expand([
      19.   19 param('','','请输入邮箱名'),
      20.   20 param('dgfa', 'fh','您输入的邮箱名格式不正确'),
      21.   21 param('gsd@sina.com', 'dhdhg', '登录名或密码错误')
      22.   22 ])
      23.   23 def test_username_password_error(self,username,password,result):
      24.   24 '''新浪首页:验证用户名和密码异常时登录'''
      25.   25 self.driver.find_element(By.ID,'freename').send_keys(username)
      26.   26 self.driver.find_element(By.ID,'freepassword').send_keys(password)
      27.   27 self.driver.find_element(By.LINK_TEXT,"登录").click()
      28.   28 t.sleep(5)
      29.   29 devText=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]')
      30.   30 t.sleep(3)
      31.   31 self.assertEqual(devText.text,result)
      32.   32
      33.   33 if __name__ == '__main__':
      34.   34 unittest.main()

      15、测试报告的生成
        通过在test的包下创建一个run.py文件,导入第三方的库HTMLTestRunner,加载所有的测试模块来生成HTML报告,代码如下:
        (unittest生成测试报告需要借助第三方的库HtmlTestRunner.py的文件)

      1. 1 import unittest
      2.    2 import os
      3.    3 import HTMLTestRunner
      4.    4
      5.    5 def allTests():
      6.    6 #获取要执行的测试模块
      7.    7 suite=unittest.TestLoader().discover(
      8.    8 #start_dir指的是测试模块的路径
      9.    9 start_dir=os.path.dirname(__file__),
      10.   10 #pattern通过正则方式加载所有测试模块
      11.   11 pattern="test_*.py")
      12.   12 return suite
      13.   13
      14.   14 def run():
      15.   15 filename=os.path.join(os.path.dirname(__file__),'report','index.html')
      16.   16 fp=open(filename,"wb")
      17.   17 runner=HTMLTestRunner.HTMLTestRunner(
      18.   18 stream=fp,
      19.   19 title='UI自动化测试',
      20.   20 description='ui test'
      21.   21 )
      22.   22 runner.run(allTests())
      23.   23
      24.   24 if __name__ == '__main__':
      25.   25 run()

  • 相关阅读:
    【物理】不脱离外圆面问题
    实验室LIMS管理系统能够解决那些企业难题
    汽车MCU虚拟化--对中断虚拟化的思考(1)
    【表面缺陷检测】表面缺陷检测数据集汇总
    【面向对象】代码存一存
    全面吃透Stream流,让代码更优雅
    chrome插件通过下载实现导出文件
    1、云原生安全之K8S的部署与常用命令
    利用SPSS对影响环境的因素分析
    GEO生信数据挖掘(二)下载基因芯片平台文件及注释
  • 原文地址:https://blog.csdn.net/okcross0/article/details/126021788