IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 【软件测试】unittest框架 -> 正文阅读

[开发测试]【软件测试】unittest框架

1.junit 和unittest框架

  • 相同点:都是单元测试
  • junit (java)是白盒测试,unittest(pathon)是黑盒测试

2.unittest框架简介

1.unittest 是python 的单元测试框架,提供了创建测试用例,测试套件以及批量执行的方案,
2.unittest 在安装pyhton 以后就直接自带了,直接import unittest 就可以使用。
3.作为单元测试的框架, unittest 也是可以对程序最小模块的一种敏捷化的测试。利用单元测试框架,创建一个类,该类继承unittest的TestCase,这样可以把每个case看成是一个最小的单元, 由测试容器组织起来,到时候直接执行,同时引入测试报告.

3.unittest框架的构成

在这里插入图片描述

  • test fixture(测试固件)
    做一些测试过程中必须要有的东西初始化和清理测试环境,比如创建临时的数据库,文件和目录等,其中 setUp() 【初始化】和 TearDown()【UI功能测试后的清理】是最常用的方法 每个测试用例执行的时候,setUp() 和 TearDown()都会执行

  • test case(单元测试用例),以 test_开头,TestCase 是编写单元测试用例最常用的类
    -== test suite(测试套件)==:单元测试用例的集合,把不同测试用例组合一起执行。

  • test runner:执行单元测试

  • == test report==:生成测试报告

class TestCase(unittest.TestCase):
	#测试固件
    def setUp(self):
        print("开始执行用例")
	#
    def test_1(self):
        print("用例1")

    def test_2(self):
        print("用例2")
	#测试固件
    def tearDown(self):
        print("用例执行结束")
#if __name__下面的代码只在当前文件生效,其他文件引用该文件,不会执行下面代码
if __name__ == '__main__':
    unittest.main()
#1.导包
#1.导包
from selenium import webdriver
import unittest
import time
#Baidu1继承自unittest.TestCase类
class Baidu1(unittest.TestCase):
    #self代表类的实例,每个方法的第一个参数,调用这个方法可以不需要传递
    def setUp(self):
        #self.driver是全局变量,只有一个driver是一个局部变量
        print(".......setup........")
        self.driver=webdriver.Chrome();
        self.url="http://www.baidu.com/"
        self.driver.maximize_window()
    def tearDown(self):
        print("........teardown......")
        self.driver.quit()

     #以test_开头的方法都是测试用例
    # 跳过测试用例
    #@unittest.skip("skipping")
    def test_hao(self):
        #创建一个局部变量等于self.driver
        driver=self.driver
        driver.get(self.url)
        time.sleep(3)
        driver.find_element_by_link_text("hao123").click()
        time.sleep(6)

    # 以test_开头的方法都是测试用例
    # 跳过测试用例
    # @unittest.skip("skipping")
    def test_baiduSearch(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__下面的代码只在当前文件生效,其他文件引用该文件,不会执行下面代码
    #像public static void mian,但不是程序入口
    if __name__ == "__main__":
        #verbosity=1和2代表打印信息的详细程度
        unittest.main(verbosity=1)
    '''
    可以增加verbosity参数,例如unittest.main(verbosity=2)
在主函数中,直接调用main() ,在main中加入verbosity=2 ,这样测试的结果就会显示的更加详细。
这里的verbosity 是一个选项, 表示测试结果的信息复杂度,有三个值:
0 ( 静默模式): 你只能获得总的测试用例数和总的结果比如总共100个失败,20 成功80
1 ( 默认模式): 非常类似静默模式只是在每个成功的用例前面有个“ . ” 每个失败的用例前面有个“F”
2 ( 详细模式): 测试结果会显示每个测试用例的所有相关的信息
    '''

4.批量执行测试脚本(构建测试套件

开发人员通常都需要编写多个测试用例才能对某一软件功能进行比较完整的测试,这些相关的测试用例称为一个测试用例集。,在unittest中是用TestSuite 类来表示的

假设我们已经编写了testbaidu1.py,testbaidu2.py两个文件,那么我们怎么同时执行这两个文件
testbaidu1.py

from selenium import webdriver
import unittest
import time
from selenium.common.exceptions import NoAlertPresentException
from selenium.common.exceptions import NoSuchElementException

class Baidu1(unittest.TestCase):
#test fixture,初始化环境
    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()
	#测试用例,必须以test开头
    # @unittest.skip("skipping")
    def test_hao(self):
        driver=self.driver
        driver.get(self.url)
        time.sleep(6)
        print(driver.title)
        #断言
        self.assertNotEqual(driver.title, "百度一下,你就知道", msg="不相等!")
        driver.find_element_by_link_text("hao123").click()
        time.sleep(6)


    def test_baidusearch(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.assertTrue("hello"=="heeell", msg="not equal!")
        time.sleep(6)

    # 判断element是否存在,可删除
    def is_element_present(self, how, what):
        try:
            self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e:
            return False
        return True
    # 判断alert是否存在,可删除
    def is_alert_present(self):
        try:
            self.driver.switch_to.alert
        except NoAlertPresentException as e:
            return False
        return True
    # 关闭alert,可删除
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to.alert
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    if __name__=="__main__":
        unittest.main(verbosity=1)
from selenium import webdriver
import unittest
import time
from selenium.common.exceptions import NoAlertPresentException
from selenium.common.exceptions import NoSuchElementException

class Baidu2 (unittest.TestCase) :
    def setUp(self):
        # print("____setUp方法")
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.baidu.com/"
        self.driver.maximize_window()
        self.verificationErrors=[]
        self.accept_next_alert = True
    def tearDown(self):
        # print("____tearDown方法")
        self.driver.quit()
        self.assertEqual([], self.verificationErrors)

    # @unittest.skip("skipping")
    def test_hao(self):
        driver = self.driver
        driver.get(self.base_url)
        driver.find_element_by_link_text("新闻").click()
        time.sleep(6)
        self.assertTrue("123" == "1234", msg="not true")
        time.sleep(3)

    def test_baidusearch(self):
        driver = self.driver
        driver.get(self.base_url)
        driver.find_element_by_id("kw").clear()
        driver.find_element_by_id("kw").send_keys(u"张艺兴")
        driver.find_element_by_id("su").click()
        time.sleep(6)
        self.assertNotEqual("张艺兴_搜索", driver.title, msg="网页未打开!")
        self.assertTrue("张艺兴_搜索" == driver.title, msg="表达式不相等!")
        time.sleep(6)
    # 判断element是否存在,可删除
    def is_element_present(self, how, what):
        try:
            self.driver.find_element(by=how, value=what)
        except NoSuchElementException as e:
            return False
        return True
    # 判断alert是否存在,可删除
    def is_alert_present(self):
        try:
            self.driver.switch_to.alert
        except NoAlertPresentException as e:
            return False
        return True
    # 关闭alert,可删除
    def close_alert_and_get_its_text(self):
        try:
            alert = self.driver.switch_to.alert
            alert_text = alert.text
            if self.accept_next_alert:
                alert.accept()
            else:
                alert.dismiss()
            return alert_text
        finally: self.accept_next_alert = True
    if __name__ == "__main__":
        unittest.main(verbosity=2)

4.1 第一种方法 addTest():把测试用例一个一个添加到脚本中

当有多个或者几百测试用例的时候, 这样就需要一个测试容器( 测试套件) ,把测试用例放在测试套件进行执行,unittest 模块中提供了TestSuite 类来生成测试套件使用该类的构造函数可以生成一个测试套件的实例,该类提供了addTest来把每个测试用例加入到测试套件中。

runall.py

import unittest
import testbaidu1
import testbaidu2

def createsuite():
    #addTest()
    #
    suite=unittest.TestSuite()
    #类名.方法名(“测试用例”)
    suite.addTest(testbaidu1.Baidu1("test_hao"))
    suite.addTest(testbaidu1.Baidu1("test_baidusearch"))

    suite.addTest(testbaidu2.Baidu2("test_hao"))
    suite.addTest(testbaidu2.Baidu2("test_baidusearch"))
    return suite
#if __name__下面的代码只在当前文件生效,其他文件引用该文件,不会执行下面代码
#if下面可以写任意代码(包括调用当前函数)
if __name__=="__main__":
    suite = createsuite()
    unittest.TextTestRunner(verbosity=1).run(suite)

addTest()的缺点

1.需要导入所有的py文件,比如import testbaidu1,每新增一个需要导入一个
2.addTest需要增加所有的testcase,如果一个py文件中有10个case,就需要增加10次

4.2 第二种makeSuite():类添加,把一个测试脚本中的所有测试用例添加到测试套件中

在unittest 框架中提供了makeSuite() 的方法,makeSuite可以实现把测试用例类内所有的测试case组成的测试套件TestSuite ,unittest 调用makeSuite的时候,只需要把测试类名称传入即可。

import unittest
import testbaidu1
import testbaidu2

def createsuite():
	 # makesuit
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(testbaidu1.Baidu1))
    suite.addTest(unittest.makeSuite(testbaidu2.Baidu2))
    return suite

#if __name__下面的代码只在当前文件生效,其他文件引用该文件,不会执行下面代码
#if下面可以写任意代码(包括调用当前函数)
if __name__=="__main__":
    suite = createsuite()
  	unittest.TextTestRunner(verbosity=1).run(suite)


4.3 第三种TestLoader()的应用:类添加,把一个测试脚本中的所有测试用例添加到测试套件中

TestLoader 用于创建类和模块的测试套件,只需要把测试类名称传入即可。一般的情况下,使TestLoader().loadTestsFromTestCase(TestClass)来加载测试类

import unittest
import testbaidu1
import testbaidu2

def createsuite():
	 #TestLoader
    suite1=unittest.TestLoader.loadTestsFromTestCase(testbaidu1.Baidu1)
    suite2=unittest.TestLoader.loadTestsFromTestCase(testbaidu2.Baidu2)
    suite = unittest.TestSuite([suite1, suite2])
    return suite
#if __name__下面的代码只在当前文件生效,其他文件引用该文件,不会执行下面代码
#if下面可以写任意代码(包括调用当前函数)
if __name__=="__main__":
    suite = createsuite()
    runner = unittest.TextTestRunner(verbosity=1)
    runner.run(suite)

4.4 第四种discover()执行文件夹下面的所有测试用例**

import unittest
import testbaidu1
import testbaidu2
def createsuite():
 #discover
    discover = unittest.defaultTestLoader.discover("../src0716", pattern="testbaidu*.py", top_level_dir=None)
    print(discover)
    return discover

#if __name__下面的代码只在当前文件生效,其他文件引用该文件,不会执行下面代码
#if下面可以写任意代码(包括调用当前函数)
if __name__=="__main__":
    suite = createsuite()
    unittest.TextTestRunner(verbosity=1).run(suite)

5.用例的执行顺序

unittest 框架默认加载测试用例的顺序是根据ASCII 码的顺序,数字与字母的顺序为: 0~9 AZ,az

忽略某用例的执行

在用例前面加上@unittest.skip(“skipping”)

6.unittest断言(预判结果是否正确)

自动化的测试中, 对于每个单独的case来说,一个case的执行结果中, 必然会有期望结果与实际结果,在unittest 的库中提供了大量的实用方法来检查预期值与实际值, 来验证case的结果。
在这里插入图片描述

下面例子相等,所以直接运行成功
在这里插入图片描述
下面例子不相等,则运行失败,输出msg中的内容
在这里插入图片描述

也可以在 IDE(录制脚本)中生成断言

7…HTML报告生成

脚本执行完毕之后,还需要看到HTML报告,
下面我们就通过HTMLTestRunner.py 来生成测试报告(百度云中有) ,下载后将其放在此目录下。
在这里插入图片描述

import time
import unittest

def createsuite():
    discovers = unittest.defaultTestLoader.discover("../src0716", pattern="testbaidu*.py", top_level_dir=None)
    print(discovers)
    return discovers

if __name__=="__main__":
    #1,创建一个文件夹
    curpath = sys.path[0]
    print(sys.path)
    print(sys.path[0])
    # 当前路径下resultreport文件夹不存在的时候,就创建一个
    if not os.path.exists(curpath+'/resultreport'):
        os.makedirs(curpath+'/resultreport')

    # 2,解决重复命名的问题
    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'
    # 打开 HTML 文件, wb 以写的方式
    with open(filename, 'wb') as fp:
        # 括号里的参数是 HTML 报告里面的参数
        runner = HTMLTestRunner.HTMLTestRunner(stream=fp, title=u"测试报告",
                                               description=u"用例执行情况", verbosity=2)
        suite = createsuite()
        runner.run(suite)

在这里插入图片描述
生成html测试报告
在这里插入图片描述

8.异常捕捉与错误截图

定义一个函数
1.捕捉错误截图的存储位置
2.解决重复命名的问题
3.截图

  # 截图函数
    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)

在这里插入图片描述

from selenium import webdriver
import unittest
import time
import os

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()

9.数据驱动(ddt)

参考添加链接描述
将测试数据和代码分开写

  • ddt的安装
pip install ddt
  • dd.ddt:
    装饰类,也就是继承自TestCase的类。
  • ddt.data:
    装饰测试方法。参数是一系列的值。
  • ddt.file_data:
    装饰测试方法。参数是文件名。文件可以是json 或者 yaml类型。
    注意,如果文件以”.yml”或者”.yaml”结尾,ddt会作为yaml类型处理,其他所有文件都会作为json文件处理。如果文件中是列表,每个列表的值会作为测试用例参数,同时作为测试用例方法名后缀显示。如果文件中是字典,字典的key会作为测试用例方法的后缀显示,字典的值会作为测试用例参数。
  • ddt.unpack:
    传递的是复杂的数据结构时使用。比如使用元组或者列表,添加unpack之后,ddt会自动把元组或者列表对应到多
    个参数上。字典也可以这样处理。
rom selenium import webdriver
import unittest
import time
from ddt import ddt, unpack, data, file_data
import sys, csv


def getCsv(file_name):
    rows = []
    path = sys.path[0]

    with open(path+'/data/'+file_name, 'rt') as f:
        readers = csv.reader(f, delimiter=',', quotechar='|')
        next(readers, None)
        for row in readers:
            temprows=[]
            for i in row:
                temprows.append(i)
            rows.append(temprows)
        return rows

@ddt
class Baidu1(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(30)
        self.base_url = "http://www.baidu.com/"
        self.driver.maximize_window()
        self.verificationErrors=[]
        self.accept_next_alert = True
    def tearDown(self):
        self.driver.quit()
        self.assertEqual([],self.verificationErrors)
    # @unittest.skip("skipping")
    @file_data('test_baidu_data.json')
    #
    #([周迅,周迅_百度搜索],[张国荣,张国荣_百度搜索],[张一山,张一三_百度搜索])
    #@unpack
    # @data("王凯", "Lisa", "特朗普", "蒋欣")
    def test_baidu1(self, value):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.maximize_window()
        driver.find_element_by_id("kw").clear()
        driver.find_element_by_id("kw").send_keys(value)
        driver.find_element_by_id("su").click()
        #time.sleep(6)
        #self.assertEqual(driver.title, expected_value, msg="搜索结果和期望不一致!")
        time.sleep(3)

    @unittest.skip("skipping")
    @data(*getCsv('test_baidu_data.txt'))
    # ([周迅, 周迅_百度搜索], [张国荣, 张国荣111_百度搜索], [张一山,张一三_百度搜索])
    # @data(['Lisa', u"Lisa_百度搜索"], [u"双笙", u"7887双笙_百度搜索"])
    @unpack
    def test_baidu2(self, value, expected_value):
        driver = self.driver
        driver.get(self.base_url + "/")
        driver.find_element_by_id("kw").clear()
        driver.find_element_by_id("kw").send_keys(value)
        driver.find_element_by_id("su").click()
        driver.maximize_window()
        time.sleep(6)
        #判断搜索网页的title和我们期望的是否一致
        self.assertEqual(expected_value, driver.title, msg="和预期搜索结果不一致!")
        print(expected_value)
        print(driver.title)
        time.sleep(6)

if __name__ == '__main__':
    unittest.main()
  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2021-08-28 09:38:55  更:2021-08-28 09:40:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/13 3:42:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码