Unittest单元测试框架全栈知识

发表于:2022-7-26 09:45

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:$Cch$    来源:博客园

  对一个测试的系统,开始最佳的测试就是源代码级别的测试,也就是单元测试阶段,这个过程也被成为白盒测试。单元测试是最基本也是最底层的测试类型,单元测试应用最基本的软件代码,如类,函数。方法等,单元测试通过可执行的断言检查被测单元的输出是否满足预期结果。在测试金字塔的理论上来说,越往下的测试投入资源越高,得到的回报率越大。
  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的入门示例
    import unittest
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.action_chains import ActionChains
    import time as t
    
    def add(a,b):
        return a+b
    
    class TestAdd(unittest.TestCase):
       def test_add_int(self):
           assert add(3,5)==8
  9、百度首页测试示例(test_baidu),测试固件每次执行
   1 import unittest
   2 from selenium import webdriver
   3 from selenium.webdriver.common.by import By
   4 from selenium.webdriver.common.action_chains import ActionChains
   5 from test.init import Init
   6 import time as t
   7 
   8 class TestBaidu(Init):
   9     def setUp(self) -> None:
  10         self.driver = webdriver.Chrome()
  11         self.driver.maximize_window()
  12         self.driver.get("https://www.baidu.com/")
  13 
  14 
  15     def tearDown(self) -> None:
  16         self.driver.quit()
  17 
  18 
  19     def test_baidu_title(self):
  20         '''百度首页:验证百度的title是否正确'''
  21         # assert self.driver.title=="百度一下,你就知道"
  22         self.assertEqual(self.driver.title, "百度一下,你就知道")
  23 
  24 
  25     def test_baidu_url(self):
  26         '''百度首页:验证百度的网址是否正确'''
  27         # 浏览器输入网址必须为https,域名后边必须有斜杠
  28         # assert self.driver.current_url=="https://www.baidu.com/"
  29         self.assertEqual(self.driver.current_url, "https://www.baidu.com/")
  30 
  31 
  32     def test_baidu_so(self):
  33         '''百度首页:验证搜索框输入的关键字是否是接口测试'''
  34         so = self.driver.find_element(By.ID, 'kw')
  35         so.send_keys("接口测试")
  36         # assert so.get_attribute("value")=="接口测试"
  37         self.assertEqual(so.get_attribute("value"), "接口测试")
  38 
  39 
  40     def test_baidu_enabled(self):
  41         '''百度首页:验证搜索框是否可编辑'''
  42         so = self.driver.find_element(By.ID, 'kw')
  43         self.assertTrue(so.is_enabled())
  44 
  45     def test_baidu_displayed(self):
  46         '''百度首页:验证关于百度的字条是否可见'''
  47         so = self.driver.find_element(By.LINK_TEXT, '关于百度')
  48         self.assertTrue(so.is_displayed())
  49 
  50     def test_baidu_setting(self):
  51         '''百度首页:验证百度首页的设置的搜索设置是否打开'''
  52         t.sleep(3)
  53         setting=self.driver.find_element(By.XPATH,'//*[@id="s-usersetting-top"]')
  54         action=ActionChains(driver=self.driver)
  55         action.move_to_element(setting).perform()
  56         self.driver.find_element(By.XPATH,'//*[@id="s-user-setting-menu"]/div/a[1]/span').click()
  57         t.sleep(3)
  58         soSet=self.driver.find_element(By.XPATH,'//*[@id="wrapper"]/div[6]/div/div/ul/li[1]')
  59         # assert devText.text=="搜索设置"
  60         self.assertEqual(soSet.text,"搜索设置")
  61 
  62 if __name__ == '__main__':
  63     unittest.main()
  10、使用setUpClass() and tearDownClass()类的百度首页测试,测试固件只执行一次
   1 import unittest
   2 from selenium import webdriver
   3 from selenium.webdriver.common.by import By
   4 from selenium.webdriver.common.action_chains import ActionChains
   5 from test.init import Init
   6 import time as t
   7 
   8 class TestBaidu(Init):
   9     class TestBaidu(Init):
  10         #使用setUpClass()方法
  11         @classmethod
  12         def setUpClass(cls) -> None:
  13             cls.driver = webdriver.Chrome()
  14             cls.driver.maximize_window()
  15             cls.driver.get('http://www.baidu.com')
  16             cls.driver.implicitly_wait(30)
  17         #使用tearDownClass()类方法
  18         @classmethod
  19         def tearDownClass(cls) -> None:
  20             cls.driver.quit()
  21 
  22 
  23     def test_baidu_title(self):
  24         '''百度首页:验证百度的title是否正确'''
  25         # assert self.driver.title=="百度一下,你就知道"
  26         self.assertEqual(self.driver.title, "百度一下,你就知道")
  27 
  28 
  29     def test_baidu_url(self):
  30         '''百度首页:验证百度的网址是否正确'''
  31         # 浏览器输入网址必须为https,域名后边必须有斜杠
  32         # assert self.driver.current_url=="https://www.baidu.com/"
  33         self.assertEqual(self.driver.current_url, "https://www.baidu.com/")
  34 
  35 
  36     def test_baidu_so(self):
  37         '''百度首页:验证搜索框输入的关键字是否是接口测试'''
  38         so = self.driver.find_element(By.ID, 'kw')
  39         so.send_keys("接口测试")
  40         # assert so.get_attribute("value")=="接口测试"
  41         self.assertEqual(so.get_attribute("value"), "接口测试")
  42 
  43 
  44     def test_baidu_enabled(self):
  45         '''百度首页:验证搜索框是否可编辑'''
  46         so = self.driver.find_element(By.ID, 'kw')
  47         self.assertTrue(so.is_enabled())
  48 
  49     def test_baidu_displayed(self):
  50         '''百度首页:验证关于百度的字条是否可见'''
  51         so = self.driver.find_element(By.LINK_TEXT, '关于百度')
  52         self.assertTrue(so.is_displayed())
  53 
  54     def test_baidu_setting(self):
  55         '''百度首页:验证百度首页的设置的搜索设置是否打开'''
  56         t.sleep(3)
  57         setting=self.driver.find_element(By.XPATH,'//*[@id="s-usersetting-top"]')
  58         action=ActionChains(driver=self.driver)
  59         action.move_to_element(setting).perform()
  60         self.driver.find_element(By.XPATH,'//*[@id="s-user-setting-menu"]/div/a[1]/span').click()
  61         t.sleep(3)
  62         soSet=self.driver.find_element(By.XPATH,'//*[@id="wrapper"]/div[6]/div/div/ul/li[1]')
  63         # assert devText.text=="搜索设置"
  64         self.assertEqual(soSet.text,"搜索设置")
  65 
  66 if __name__ == '__main__':
  67     unittest.main()
  11、assert的常用方式:
  assertEqual():比较的是两个对象的==关系
  assertIn():比较的是两个对象的包含关系
  assertIs():比较两个字符串的内存地址
  assertTrue()
  assertFalse()
  12、测试固件的分离
  在UI自动化测试中,所有的测试固件的部分的代码都是相同的,所以为了避免重复代码,提高效率,采用了测试固件分离的思想,使用继承的思想,把测试固件分离,这样的
  好处是只需要在一个地方维护测试固件,而不是多个地方维护。其他的测试类只需要继承测试固件就可以使用了。
  把测试固件分离到init.py里面,代码具体如下:
   1 import unittest
   2 from selenium import webdriver
   3 
   4 class Init(unittest.TestCase):
   5     def setUp(self) -> None:
   6         self.driver=webdriver.Chrome()
   7         self.driver.maximize_window()
   8         self.driver.get("https://www.baidu.com/")
   9 
  10     def tearDown(self) -> None:
  11         self.driver.quit()
  在其它测试模块可中导入这个Init类,然后再继承这个类,具体代码如下:
   1 import unittest
   2 from selenium import webdriver
   3 from selenium.webdriver.common.by import By
   4 from selenium.webdriver.common.action_chains import ActionChains
   5 #测试固件分离思想,导入Init类
   6 from test.init import Init  
   7 import time as t
   8 #在测试类中继承Init类
   9 class TestBaidu(Init):
  10     def setUp(self) -> None:
  11         self.driver=webdriver.Chrome()
  12         self.driver.maximize_window()
  13         self.driver.get("https://www.baidu.com/")
  14 
  15     def tearDown(self) -> None:
  16         self.driver.quit()
  17 
  18     def test_baidu_title(self):
  19         '''百度首页:验证百度的title是否正确'''
  20         # assert self.driver.title=="百度一下,你就知道"
  21         self.assertEqual(self.driver.title,"百度一下,你就知道")
  22 
  23     def test_baidu_url(self):
  24         '''百度首页:验证百度的网址是否正确'''
  25         #浏览器输入网址必须为https,域名后边必须有斜杠
  26         # assert self.driver.current_url=="https://www.baidu.com/"
  27         self.assertEqual(self.driver.current_url,"https://www.baidu.com/")
  28 if __name__ == '__main__':
  29     unittest.main()
  13、新浪首页示例
   1 import unittest
   2 from selenium import webdriver
   3 from selenium.webdriver.common.by import By
   4 from selenium.webdriver.common.action_chains import ActionChains
   5 import time as t
   6 
   7 class TestSina(unittest.TestCase):
   8     def setUp(self) -> None:
   9         self.driver=webdriver.Chrome()
  10         self.driver.maximize_window()
  11         self.driver.get("https://mail.sina.com.cn/#")
  12         self.driver.implicitly_wait(30)
  13 
  14     def tearDown(self) -> None:
  15         self.driver.quit()
  16 
  17     def test_username_null(self):
  18         '''新浪首页:验证用户名为空时,直接登录时的提示信息是否正确'''
  19         self.driver.find_element(By.CLASS_NAME, "loginBtn").click()
  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         self.assertEqual(devText.text, '请输入邮箱名')
  22 
  23     def test_email_error(self):
  24         '''新浪首页:验证用户名的格式错误时登录的提示信息是否正确'''
  25         self.driver.find_element(By.ID, 'freename').send_keys("dgg")
  26         self.driver.find_element(By.ID, 'freepassword').send_keys("fhsk")
  27         self.driver.find_element(By.CLASS_NAME, "loginBtn").click()
  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         self.assertEqual(devText.text, '您输入的邮箱名格式不正确')
  30 
  31     def test_username_password_error(self):
  32         '''新浪首页:验证用户名和密码错误时登录的提示信息是否正确'''
  33         self.driver.find_element(By.ID, 'freename').send_keys("134467@sina.com")
  34         self.driver.find_element(By.ID, 'freepassword').send_keys("fhsk")
  35         self.driver.find_element(By.LINK_TEXT, "登录").click()
  36         t.sleep(5)
  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         t.sleep(3)
  39         self.assertEqual(devText.text, '登录名或密码错误')
  40 
  41     if __name__ == '__main__':
  42         unittest.main()
  14、参数化
  当一个测试场景,它的测试步骤相同,测试数据不一样的时候,那么就可以使用参数化的思想来解决。
  在unittest测试框架中,参数化需要借助第三方的库parameterized,先使用命令pip install parameterized安装 parameterized库,再具体应用参数化思想,代码如下:
   1 import unittest
   2 from selenium import webdriver
   3 from selenium.webdriver.common.by import By
   4 from selenium.webdriver.common.action_chains import ActionChains
   5 from parameterized import parameterized,param
   6 import time as t
   7 
   8 class TestSina(unittest.TestCase):
   9     def setUp(self) -> None:
  10         self.driver=webdriver.Chrome()
  11         self.driver.maximize_window()
  12         self.driver.get("https://mail.sina.com.cn/#")
  13         self.driver.implicitly_wait(30)
  14 
  15     def tearDown(self) -> None:
  16         self.driver.quit()
  17 
  18     @parameterized.expand([
  19         param('','','请输入邮箱名'),
  20         param('dgfa', 'fh','您输入的邮箱名格式不正确'),
  21         param('gsd@sina.com', 'dhdhg', '登录名或密码错误')
  22     ])
  23     def test_username_password_error(self,username,password,result):
  24         '''新浪首页:验证用户名和密码异常时登录'''
  25         self.driver.find_element(By.ID,'freename').send_keys(username)
  26         self.driver.find_element(By.ID,'freepassword').send_keys(password)
  27         self.driver.find_element(By.LINK_TEXT,"登录").click()
  28         t.sleep(5)
  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         t.sleep(3)
  31         self.assertEqual(devText.text,result)
  32 
  33 if __name__ == '__main__':
  34     unittest.main()
  15、测试报告的生成
  通过在test的包下创建一个run.py文件,导入第三方的库HTMLTestRunner,加载所有的测试模块来生成HTML报告,代码如下:
  (unittest生成测试报告需要借助第三方的库HtmlTestRunner.py的文件)
   1 import unittest
   2 import os
   3 import HTMLTestRunner
   4 
   5 def allTests():
   6     #获取要执行的测试模块
   7     suite=unittest.TestLoader().discover(
   8     #start_dir指的是测试模块的路径
   9         start_dir=os.path.dirname(__file__),
  10     #pattern通过正则方式加载所有测试模块
  11         pattern="test_*.py")
  12     return suite
  13 
  14 def run():
  15     filename=os.path.join(os.path.dirname(__file__),'report','index.html')
  16     fp=open(filename,"wb")
  17     runner=HTMLTestRunner.HTMLTestRunner(
  18         stream=fp,
  19         title='UI自动化测试',
  20         description='ui test'
  21     )
  22     runner.run(allTests())
  23 
  24 if __name__ == '__main__':
  25     run()
  生成的html报告如下:
  本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号