【如何学习Python自动化测试】—— Python 的 unittest 框架

简介: 【如何学习Python自动化测试】—— Python 的 unittest 框架

10 、Python 的 unittest 框架

10.1 Unittest 框架介绍

     Unittest是Python语言中的一种测试框架,是Python标准库中的一个模块。它可以帮助开发者编写自动化测试,可以进行单元测试、集成测试、功能测试等各种类型的测试。 Unittest的特点是简单易学,文档齐全,可以为每个测试用例创建独立的环境,可以根据测试结果输出详细的测试报告。

     Unittest模块中提供了很多方便测试的工具,如assertEqual、assertTrue、assertFalse、assertRaises等。使用Unittest测试框架可以提高开发的质量和效率,有效减少开发期和维护期中出现的问题,对于大型项目特别是团队合作开发中,使用Unittest测试框架可以提高代码的可维护性,降低开发和维护的成本。

     Unittest 是 python 的单元测试框架,原名为 PyUnit,由 java 的 junit 演化而来。

     Unittest 提供了 test case、test suites、test fixtures、test runnet。

  • Test case(测试用例):是一个单独的测试单元,用于测试一个或多个特定的代码路径。
  • Test suite(测试套件):是一系列测试用例的集合。测试套件是按照测试计划所定义的各个阶段的测试目标决定的,即先有测试计划,后面才有测试套件。
  • Test fixture(测试固件):是为测试提供必要的环境和资源(如数据库连接)的代码。在测试之前和之后执行。(setup + test case + teardown 的组合)
  • Test runner(测试运行器):是执行多个测试用例或测试套件的程序组件。它收集测试结果并生成测试报告。

     在 Python 中,unittest 是一个内置的测试框架,可用于编写单元测试。它提供了类和方法来组织和运行测试用例。使用 unittest,我们可以轻松地编写和运行单元测试并生成详细的测试报告。

     Unittest 结构:

10.2 Unittest 框架详解

10.2.1 测试用例

     在 unittest 中没有明确究竟 test 的 class 是测试用例,还是 class 中的 test 开头的方法 是测试用例,在下面的案例中,我们将 test 开头的方法作为测试用例来执行。

     先看一个简单的案例:

import unittest
在使用 unittest 框架时,需要先导入 unittest
class login_test(unittest.TestCase):
创建一个测试类,该类继承 unittest 的 TestCase。 
  def setUp(self):
    Setup 是测试执行之前的操作, 会在用例执行之前先执行这里的内容,通常用来初始化环境
    self.testa=10
    self.testb=10
    
  def test_login(self):
    要执行的测试 1
    self.assertTrue(self.testa == self.testb)
    
  def test_login2(self):
    要执行的测试 2
    try:
    self.testc=30
    self.assertTrue(self.testa == self.testc)
    except AssertionError:
    self.fail("test is false")
    
  def tearDown(self):
    执行结束之后的操作, 通常用来执行还原测试环境的操作
    print('Test Runner End')
    
if __name__ == '__main__':
  unittest.main()
  调用 unittest 的开始执行

     在使用 unittest 前,需要先导入 unittest 的包,在这个包中包含了 unittest 提供的各种类,如:TestCase、TestSuite、TextTestRunner、TestLoader、main 等等。

     创建一个 login_test 的 class,用来测试,该类继承 TestCase,从而能够使用 TestCase 中的方法。

     Setup 方法是 TestCase 中的方法,这里是重写 TestCase 的 setup 方法,该方 法用来做测试执行前的操作,比如构建测试数据,打开浏览器、链接数据库等操作。

     下面的 tearDown 方法相同,区别在不该方法用于执行测试执行结束后的操作,比如关闭浏览器,释放数据库连接操作。

     中间以 test 开头的方法,则会被当做测试用例来执行,运行该脚本时,unittest 会自动加载这些 test 开头的方法,来执行测试。

     Unitest.main 是调用 unittest 的执行方法,这里是测试执行的入口。

10.2.2 测试套

     测试套又称测试集,也叫测试套件,通常是一组测试用例的集合,通过 suite 可以执行一组测试用例。 下面的代码是针对 LMD 的登陆测试,如果登陆成功,则获取他的 title,判断 title 是否不预期结果一致,如果一致,则测试成功,否则用例执行失败。 这个案例通过 suite 实现的。代码如下:

#coding=utf-8
__author__ = 'Administrator'
import unittest
from selenium import webdriver
import HTMLTestRunner
from selenium.webdriver.support import expected_conditions
class login_test2(unittest.TestCase) :
  def setUp(self):
    self.driver = webdriver.Firefox()
    self.driver.maximize_window()
  def test_login(self):
    driver = self.driver
    driver.get('http://www.chuangyijia.com/login')
    driver.find_element_by_id('email').send_keys('810155067@qq.com')
    driver.find_element_by_id('pwd').send_keys('a654321')
    driver.find_element_by_css_selector('#submit').click()
    test=expected_conditions.title_is(u'创意家,登录') self.assertTrue(test(driver))
def tearDown(self):
  self.driver.quit()
if __name__ == '__main__':
  suite=unittest.TestLoader().loadTestsFromTestCase(login_test2)
    unittest.TextTestRunner().run(suite)

     这段代码中,上面的内容和之前没有上面差别,主要在 if name==’ main__’的内容,这句话的意思为“Make a script both importable and executable”,解释过来就是让你写的脚本模块既可以导入到别的模块中用,另外 该模块自己也可执行。试代码的时候,在”if name == ‘main’ “中加入一些 我们的调试代码,我们可以让外部模块调用的时候不执行我们的调试代码,但是如果 我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!

     Unittest.TestLoader:源代码解释为“This class is responsible for loading tests according to various criteria and returning them wrapped in a TestSuite ”意思可以通过该类完成测试用例的加载,将用例加载到 siuter 中,但是需要调用该类的 loadTestFromTestCase 方法来加载用例,该方法接收参数为测试类,也就是 我们上面定义的 login_test2 的类名。这句代码就会将该类中以 test 开头的方法加载到 suiter 中。 Suiter 变量用来接收加载后的结果。

     通过 unittest 调用他的 TextTestRunner 类中的 run 方法来执行测试,run 方法 需要将 suiter 作为参数传入。TextTestRunner 是以文本形式显示测试结果,如果测试失败,会显示失败的测试名称,并统计测试的结果。run 方法是运行传入的 case 或 suiter。

10.2.3 断言

     在编程中,通常会做一些假设,使用断言,去判断一个代码处理的结果是否和自己的预期相符,如果符合则为 True,否则为 false。在测试中,我们也会有这样的需求,执行一个测试,给一个预期结果,来断言实际结果不预期结果是否符合,不符合 则测试失败,符合则执行成功。

     在 unittest 的 TestCase 中给我们提供了很丰富的断言操作,下面罗列出了常用的一些断言。

  • assertTrue:检查表达式返回值是否为真 True ,返回值类型为布尔类型。
  • assertFalse:不上面相反,检查表达式返回是否为假 False ,布尔类型。
  • assertEqual(arg1, arg2, msg=None):验证 arg1 和 arg2 是否相等。
  • assertNotEqual(arg1, arg2, msg=None):验证 arg1 和 arg2 是否不相等。
  • assertIs(arg1, arg2, msg=None):验证 arg1 和 arg2 是否为同一个对象。
  • assertIsNot(arg1, arg2, msg=None):验证 arg1 和 arg2 是否不为同一个对象。
  • assertIsNone(expr, msg=None):验证 expr 是否为 none,是则返回 True。
  • ssertIsNotNone(expr, msg=None):验证 expr 是否不为 none,是则返回 True。
  • assertIn(arg1, arg2, msg=None):验证 arg1 是否在 arg2 中 ,是则 True
  • assertNotIn(arg1, arg2, msg=None):验证 arg1 不在 arg2 的中,是则 fail

示例:

#coding=utf-8
__author__ = 'Administrator'
import unittest
class Test_Asser(unittest.TestCase):
  def test_assertTrue(self):
    self.assertTrue(5>4)
    5>4 则返回 True,否则返回 False
    
  def test_assertFalse(self) :
    self.assertFalse(5<4)
    表达式成立则返回 False,否则返回 True
  
  def test_assertEqual(self) :
    self.assertEqual(u"中国",u"中国")
    两个字符串相等,则返回 True,否则返回 False
  
  def test_assertNotEqual(self):
    self.assertNotEqul(u"中国 1",u"中国 2")
    两个字符串不相等,返回 True,否则返回 false
  
  def test_assertIs(self):
    a=10
    a=20
    self.assertIs(a,a)
    a 是一个变量,下面的是对 a 重新赋值,所以依然是一个对象, 所以此处返回 True,否则返回 false。
  
  def test_assertIsNot(self) :
    a=10
    b=20
    self.assertIsNot(a,b)
    a 和 b 是两个变量,不属于同一个对象 ,所以此处返回 True, 否则返回 False
  
  def test_assertIsNone(self):
    a=None
    self.assertIsNone(a)
    None 在 python 中是一个特殊的空值,即表示空值,也可以表 示为空对象。在这里给 a 赋值为 None,那么 a 就是一个空对象,此处 返回 True,否则返回 false
    def test_assertIsNotNone(self):
    c=10
    self.assertIsNotNone(c)
    与上面相反, c 是一个有值的对象,这里判断 c 是不是不为 None,是则返回 True,否则返回 False。
  
  def test_assertIsIn(self):
  text="abcdef"
  t='c'
  self.assertIn(t,text)
  判断 t 的值是否在 text 中,如果在则返回 True,否则返回 False。
  def test_assertIsNotIn(self):
    text="abcdef"
    self.assertNotIn('h',text)
    判断字符 h 是否不在 text 中,不在则返回 True,否则返回 false.
    
if __name__ == '__main__':
  unittest.main()

     当然在 unittest 中不叧是这些断言,还有其他断言,后续会慢慢加入。

10.3 测试批量执行

下面做两个测试的案例,先创建目录结构:

     主目录:Lmd_auto_test

     次目录:Lmd_auto_test\test_case

     在 test_case 目录中有 login_auto.py 和 Release_Creative.py 两个脚本。

     将下面的代码保存为 login_auto.py

#coding=utf-8
__author__ = 'Administrator'
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
import time
import unittest
class login_test_case(unittest.TestCase):
  def setUp(self):
    self.driver = webdriver.Firefox()
    self.driver.maximize_window()
    self.driver.get('http://www.chuangyijia.com/login')
    def tearDown(self):
    self.driver.quit()
    
  def test_login(self):
    self.driver.find_element_by_id('email').send_keys('810155067@qq.com')
    self.driver.find_element_by_id('pwd').send_keys('a654321')
    self.driver.find_element_by_id('submit').click()
    #self.driver.implicitly wait(5)
    time.sleep(3)
    WebDriverWait(self.driver,30).until(expected_conditions.visib
    ility_of_element_located((By.CSS_SELECTOR,'.logo')))
    print self.driver.title
    is_title = expected_conditions.title_is(u'首页-创意家')  
    self.assertTrue(is_title(self.driver))
if __name__ == '__main__':
  unittest.main()

下面的文件保存为 Release_Creative.py

#coding=utf-8
__author__ = 'Administrator'
from selenium import webdriver
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.common.action_chains import ActionChains
import unittest
import sys
import os,time
class release_creat(unittest.TestCase) :
def setUp(self):
  self.driver = webdriver.Firefox()
  self.driver.maximize_window()
  self.driver.get('http://www.chuangyijia.com/login')
  
  self.driver.find_element_by_id('email').send_keys('810155067@qq.com')
  
  self.driver.find_element_by_id('pwd').send_keys('a654321')
  self.driver.find_element_by_id('submit').click()
  time.sleep(3)
  #is title = expected conditions.title is(u'首页-创意家') #self.assertTrue(is title(self.driver))
  
  def test_release(self):
    self.driver.find_element_by_css_selector('.menu >ul:nth-child(1) > li:nth-child(1) > a:nth-child(1)').click()
    self.driver.find_element_by_css_selector('.c01 > a:nth-child(1)').click()
    
    self.driver.find_element_by_name('mobile').send_keys('1943235923')
    
    self.driver.find_element_by_css_selector('.idea_name').send_k eys(u"发布中文创意")
    self.driver.find_element_by_id('province').click()
    
    self.driver.find_element_by_xpath('//option[contains(text()," 江苏")]').click()
    self.driver.find_element_by_id('city').click()
    
    self.driver.find_element_by_xpath('//option[contains(text()," 南京")]').click()
    text=u"预售管理,后台管理员可以修改时间, 并且只能修改为 当月的日期, 不能修改年月"
 
    self.driver.find_element_by_css_selector('#pForm >table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) >  tr:nth-child(6) > td:nth-child(2) > textarea:nth-child(1)').send_keys(text)
    self.driver.find_element_by_css_selector('#pForm >table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) >  tr:nth-child(7) > td:nth-child(2) > textarea:nth-child(1)').send_keys(u"没有问题。。。。 ")
    self.driver.find_element_by_css_selector('#pForm >table:nth-child(11) > tbody:nth-child(1) > tr:nth-child(1) > td:nth-child(1) > table:nth-child(1) > tbody:nth-child(1) >  tr:nth-child(8) > td:nth-child(2) > textarea:nth-child(1)').send_keys(u"不需要解决")
    
    self.driver.find_element_by_name('support_end_date').send_keys('2017-8-18')
    time.sleep(2)
    
    self.driver.find_element_by_css_selector('.c_btn').click()
    
    self.driver.find_element_by_css_selector('.c_btn').click()
    os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
    time.sleep(2)
    put2 =self.driver.find_element_by_css_selector('#upimg_1')
    put1 =self.driver.find_element_by_css_selector('.cy_pic > ul:nth-child(1) > li:nth-child(1) > input:nth-child(3)')
    
    ActionChains(self.driver).move_to_element(put2).perform()
    self.driver.find_element_by_css_selector('.cy_pic >ul:nth-child(1) > li:nth-child(1) > input:nth-child(3)').click()
    os.system("H:\\pydj\\Lmd_auto_test\\testjpg.exe")
    #self.driver.find element by_css selector('.cy_pic >ul:nth-child(1) > li:nth-child(2) > input:nth-child(3)').click()
    #os.system("H:\pydj\Lmd auto test\testjpg.exe")
    
    self.driver.find_element_by_id('saveBtn').click()
    time.sleep(2)
    is_exist = self.driver.find_element_by_css_selector('div.item:nth-child(1) > div:nth-child(2) > a:nth-child(1)')
    Creat_Name = is_exist.text
    self.assertEqual(Creat_Name,u"发布中文创意")
    #self.assertTrue(is exist)
if __name__ == '__main__':
  unittest.main()

     上面的两个文件,一个是测试登陆功能的用例,另一个是测试创意发布的用例,这里对成功和失败都做了简单的判断,例如登陆,在判断登陆后,title 是否为登陆成功的title,是则执行通过,否则执行失败。创意发布时,判断提交后,该创意是否在发布的列表中,并在第一个,如果是,则执行成功,否则执行失败。

     在 test_case 的目录中创建__init__.py 文件,文件内容如下:

#coding=utf-8
__author__ = 'Administrator'
import login_auto
import Release_Creative

     在 Lmd_auto_test 目录下创建 run_test_case.py 文件,文件主要用来实现执行 test_case 目录下的测试脚本。文件内容如下:

#coding=utf-8
__author__ = 'Administrator'
# import test case
import unittest
from test_case import login_auto,Release_Creative
suiter = unittest.TestSuite()
suiter.addTest (unittest.makeSuite(login_auto.login_test_case)) 
suiter.addTest (unittest.makeSuite(Release_Creative.release_creat))
unittest.TextTestRunner().run(suiter)


目录
相关文章
|
1月前
|
安全 前端开发 数据库
Python 语言结合 Flask 框架来实现一个基础的代购商品管理、用户下单等功能的简易系统
这是一个使用 Python 和 Flask 框架实现的简易代购系统示例,涵盖商品管理、用户注册登录、订单创建及查看等功能。通过 SQLAlchemy 进行数据库操作,支持添加商品、展示详情、库存管理等。用户可注册登录并下单,系统会检查库存并记录订单。此代码仅为参考,实际应用需进一步完善,如增强安全性、集成支付接口、优化界面等。
|
18天前
|
人工智能 开发者 Python
Chainlit:一个开源的异步Python框架,快速构建生产级对话式 AI 应用
Chainlit 是一个开源的异步 Python 框架,帮助开发者在几分钟内构建可扩展的对话式 AI 或代理应用,支持多种工具和服务集成。
110 9
|
1月前
|
JSON 安全 中间件
Python Web 框架 FastAPI
FastAPI 是一个现代的 Python Web 框架,专为快速构建 API 和在线应用而设计。它凭借速度、简单性和开发人员友好的特性迅速走红。FastAPI 支持自动文档生成、类型提示、数据验证、异步操作和依赖注入等功能,极大提升了开发效率并减少了错误。安装简单,使用 pip 安装 FastAPI 和 uvicorn 即可开始开发。其优点包括高性能、自动数据验证和身份验证支持,但也存在学习曲线和社区资源相对较少的缺点。
73 15
|
21天前
|
小程序 前端开发 关系型数据库
uniapp跨平台框架,陪玩系统并发性能测试,小程序源码搭建开发解析
多功能一体游戏陪练、语音陪玩系统的开发涉及前期准备、技术选型、系统设计与开发及测试优化。首先,通过目标用户分析和竞品分析明确功能需求,如注册登录、预约匹配、实时语音等。技术选型上,前端采用Uni-app支持多端开发,后端选用PHP框架确保稳定性能,数据库使用MySQL保证数据一致性。系统设计阶段注重UI/UX设计和前后端开发,集成WebSocket实现语音聊天。最后,通过功能、性能和用户体验测试,确保系统的稳定性和用户满意度。
|
27天前
|
关系型数据库 API 数据库
Python流行orm框架对比
Python中有多个流行的ORM框架,如SQLAlchemy、Django ORM、Peewee、Tortoise ORM、Pony ORM、SQLModel和GINO。每个框架各有特点,适用于不同的项目需求。SQLAlchemy功能强大且灵活,适合复杂项目;Django ORM与Django框架无缝集成,易用性强;Peewee轻量级且简单,适合小型项目;Tortoise ORM专为异步框架设计;Pony ORM查询语法直观;SQLModel结合Pydantic,适合FastAPI;GINO则适合异步环境开发。初学者推荐使用Django ORM或Peewee,因其易学易用。
|
1月前
|
人工智能 分布式计算 大数据
MaxFrame 产品评测:大数据与AI融合的Python分布式计算框架
MaxFrame是阿里云MaxCompute推出的自研Python分布式计算框架,支持大规模数据处理与AI应用。它提供类似Pandas的API,简化开发流程,并兼容多种机器学习库,加速模型训练前的数据准备。MaxFrame融合大数据和AI,提升效率、促进协作、增强创新能力。尽管初次配置稍显复杂,但其强大的功能集、性能优化及开放性使其成为现代企业与研究机构的理想选择。未来有望进一步简化使用门槛并加强社区建设。
70 7
|
1月前
|
存储 测试技术 API
pytest接口自动化测试框架搭建
通过上述步骤,我们成功搭建了一个基于 `pytest`的接口自动化测试框架。这个框架具备良好的扩展性和可维护性,能够高效地管理和执行API测试。通过封装HTTP请求逻辑、使用 `conftest.py`定义共享资源和前置条件,并利用 `pytest.ini`进行配置管理,可以大幅提高测试的自动化程度和执行效率。希望本文能为您的测试工作提供实用的指导和帮助。
108 15
|
2月前
|
数据采集 人工智能 自然语言处理
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
Midscene.js 是一款基于 AI 技术的 UI 自动化测试框架,通过自然语言交互简化测试流程,支持动作执行、数据查询和页面断言,提供可视化报告,适用于多种应用场景。
470 1
Midscene.js:AI 驱动的 UI 自动化测试框架,支持自然语言交互,生成可视化报告
|
2月前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
108 2
|
4月前
|
存储 算法 API
Python学习五:函数、参数(必选、可选、可变)、变量、lambda表达式、内置函数总结、案例
这篇文章是关于Python函数、参数、变量、lambda表达式、内置函数的详细总结,包含了基础知识点和相关作业练习。
63 0