【Unittest】自动化测试框架核心要素_unittest框架三要素

2、TestRunner(测试执行):用来执行 TestSuite(测试套件的)

代码:首先要准备多个测试用例的文件才可以实现TestSuite和TestRunner,以下代码是已经准备了unittest_Demo2和unittest_Demo1两个测试用例文件

1、导包

2、实例化(创建对象)套件对象

3、使用套件对象添加用例方法

4、实例化对象运行

5、使用运行对象去执行套件对象

import unittest

from unittest_Demo2 import TestDemo
from unittest_Demo1 import Demo

suite = unittest.TestSuite()

将⼀个测试类中的所有⽅法进⾏添加

套件对象.addTest(unittest.makeSuite(测试类名))

suite.addTest(unittest.makeSuite(TestDemo))
suite.addTest(unittest.makeSuite(Demo))

4、实例化运行对象

runner = unittest.TextTestRunner();

5、使用运行对象去执行套件对象

运⾏对象.run(套件对象)

runner.run(suite)

三、TestLoader(测试加载)

说明:

  1. 将符合条件的测试方法添加到测试套件中

  2. 搜索指定目录文件下指定字母开头的模块文件下test开始的方法,并将这些方法添加到测试套件中,最后返回测试套件

  3. 与Testsuite功能一样,对他功能的补充,用来组装测试用例

一般测试用例是写在Case这个文件夹里面,当测试用例超多的时候就可以考虑 TestLoader

写法:

  1. suite = unittest.TestLoader().discover(“指定搜索的目录文件”,“指定字母开头模块文件”)
  2. suite = unittest.defaultTestLoader.discover(“指定搜索的目录文件”,“指定字母开头模块文件”) 【推荐】
    注意:
    如果使用写法1,TestLoader()必须有括号。

1. 导包

2. 实例化测试加载对象并添加用例 —> 得到的是 suite 对象

3. 实例化 运行对象

4. 运行对象执行套件对象

import unittest

实例化测试加载对象并添加用例 —> 得到的是 suite 对象

unittest.defaultTestLoader.discover(‘用例所在的路径’, ‘用例的代码文件名’)

测试路径:相对路径

测试文件名:可以使用 * 通配符,可以重复使用

suite = unittest.defaultTestLoader.discover(‘./Case’, ‘cs*.py’)
runner = unittest.TextTestRunner()
runner.run(suite)

TestSuite与TestLoader区别:
共同点:都是测试套件
不同点:实现方式不同
TestSuite: 要么添加指定的测试类中所有test开头的方法,要么添加指定测试类中指定某个test开头的方法
TestLoader: 搜索指定目录下指定字母开头的模块文件中以test字母开头的方法并将这些方法添加到测试套件中,最后返回测试套件

四、Fixture(测试夹具)

是一种代码结构,在某些特定情况下,会自动执行。

4.1 方法级别

在每个测试方法(用例代码)执行前后都会自动调用的结构

def setUp(),每个测试方法执行之前都会执行 (初始化)

def tearDown(),每个测试方法执行之后都会执行 (释放)

特性:几个测试函数,执行几次。每个测试函数执行之前都会执行 setUp,执行之后都会执行tearDwon

初始化

def setUp(self):

每个测试方法执行之前执行的函数

pass

释放

def tearDown(self):

每个测试方法执行之后执行的函数

pass

场景:当你要登录自己的用户名账户的时候,都会输入网址,当你准备不用这个页面了,都会关闭当前页面;
1、输入网址 (方法级别)
2、关闭当前页面 (方法级别)

4.2 类级别

在每个测试类中所有方法执行前后 都会自动调用的结构(在整个类中 执行之前执行之后各一次)

def setUpClass() ,类中所有方法之前

def tearDownClass(),类中所有方法之后

特性:测试类运行之前运行一次setUpClass ,类运行之后运行一次tearDownClass

注意:类方法必须使用 @classmethod修饰

@classmethod
def setUpClass(cls):
print(‘-----------1.打开浏览器’)

@classmethod
def tearDownClass(cls):
print(‘------------5、关闭浏览器’)

场景:你上网的整个过程都首先需要打开浏览器,关闭浏览器,而他们整个过程都需要执行一次,那么就可以用类级别。

案列模板:结合了类级别和方法级别实现的

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBxQV2uP-1647245316010)(C:/Users/15277/AppData/Roaming/Typora/typora-user-images/image-20220303153824329.png)]

提示:
无论使用函数级别还是类级别,最后常用场景为:
初始化:

  1. 获取浏览器实例化对象
  2. 最大化浏览器
  3. 隐式等待
    结束:
    关闭浏览器驱动对象

五、断言 ☆

1、什么是断言:

让程序代替人工自动的判断预期结果和实际结果是否相符

断言的结果:

1)、True,用例通过

2)、False,代码抛出异常,用例不通过

3)、在unittest中使用断言,需要通过 self.断言方法

2、为什么要断言:

自动化脚本执行时都是无人值守,需要通过断言来判断自动化脚本的执行是否通过

注:自动化脚本不写断言,相当于没有执行测试一个效果。

3、常用的断言:

self.assertEqual(ex1, ex2) # 判断ex1 是否和ex2 相等
self.assertIn(ex1, ex2) # ex2是否包含 ex1 注意:所谓的包含不能跳字符
self.assertTrue(ex) # 判断ex是否为True

重点讲前两个assertEqual 和 assertIn
方法:
assertEqual:self.assertEqual(预期结果,实际结果) 判断的是预期是否相等实际
assertIn:self.assertIn(预期结果,实际结果) 判断的是预期是否包含实际中
assertIn(‘admin’, ‘admin’) # 包含
assertIn(‘admin’, ‘adminnnnnnnn’) # 包含
assertIn(‘admin’, ‘aaaaaadmin’) # 包含
assertIn(‘admin’, ‘aaaaaadminnnnnnn’) # 包含
assertIn(‘admin’, ‘addddddmin’) # 不是包含

Login 函数我已经封装好了,这里直接导包调用就可以了。

import unittest

from login import Login

class TestLogin(unittest.TestCase):
“”“正确的用户名和密码: admin, 123456, 登录成功”“”

def test_success(self):
self.assertEqual(‘登录成功’, Login(‘admin’, ‘123456’))

def test_username_error(self):
“”“错误的用户名: root, 123456, 登录失败”“”
self.assertEqual(‘登录失败’, Login(‘root’, ‘123456’))

def test_password_error(self):
“”“错误的密码: admin, 123123, 登录失败”“”
self.assertEqual(‘登录失败’, Login(‘admin’, ‘123123’))

def test_error(self):
“”“错误的用户名和错误的密码: aaa, 123123, 登录失败”“”

self.assertEqual(‘登录失败’,Login(‘登陆失败’,‘123123’))

self.assertIn(‘失败’, Login(‘登录失败’, ‘123123’))

六、跳过

对于一些未完成的或者不满足测试条件的测试函数和测试类, 不想执行,可以使用跳过

“”"
使用方法,装饰器完成
代码书写在 TestCase 文件
“”"

直接将测试函数标记成跳过

@unittest.skip(‘跳过条件’)

根据条件判断测试函数是否跳过 , 判断条件成立, 跳过

@unittest.skipIf(判断条件,‘跳过原因’)

import unittest

version = 20

class TestDemo1(unittest.TestCase):

@unittest.skip(‘直接跳过’)
def test_method1(self):
print(‘测试用例1-1’)

@unittest.skipIf(version > 19, ‘版本大于19,测试跳过’)
def test_method2(self):
print(‘测试用例1-2’)

结果

七、数据驱动(unittest ddt)☆

ddt:data-driver tests

数据驱动:是以数据来驱动整个测试用例的执行, 也就是测试数据决定测试结果

数据驱动解决的问题是:

1)、代码和数据分离,避免代码冗余

2)、不写重复的代码逻辑;

在python解释器中需要安装 ddt 这个包才能用:

要检查是否安装上,在cmd当中 输入 pip list命名,有ddt说明安装成功

语法:

1、使用数据驱动,要在class前加上修饰器 @ddt

说明:方法里面使用 print ,为了方便,模拟测试用例,主要是为了学习数据驱动,实际中方法里面写的是测试用例的代码

import unittest
from ddt import ddt, data

@ddt
class TestDemo(unittest.TestCase):

单一参数

@data(‘17611110000’, ‘17611112222’)
def test_1(self, phone):
print(‘测试一电话号码:’, phone)

if name == ‘main’:
unittest.main()
else:
pass

1)、结合 selenium 使用 ddt

“”"
unittest + selenium
“”"
import unittest
from time import sleep

from ddt import ddt, data
from selenium import webdriver

@ddt
class TestBaidu(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome()
self.driver.get(‘https://www.sogou.com/’)

def tearDown(self) -> None:
sleep(3)
self.driver.quit()

单一参数

@data(‘易烊千玺’, ‘王嘉尔’)
def test_01(self, name):
self.driver.find_element_by_id(‘query’).send_keys(name)
self.driver.find_element_by_id(‘stb’).click()

if name == ‘main’:
unittest.main()

self:相当于java中的this,当前对象的引用,self.driver定义了driver这个变量。

2、在实际中不可能是单一参数进行传参,将会使用多个参数进行传参:

注意事项:
1)、多个数据传参的时候@data里面是要用列表形式
2)、会用到 @unpack 装饰器 进行拆包,把对应的内容传入对应的参数;

import unittest
from ddt import ddt, data, unpack

@ddt
class TestDemo(unittest.TestCase):

多参数数据驱动

@data([‘admin’, ‘123456’])

unpack 是进行拆包,不然会把列表里面的数据全部传到username这个一个参数,我们要实现列表中的两个数据分别传入对应的变量中

@unpack
def test_2(self, username, password):
print(‘测试二:’, username, password)

if name == ‘main’:
unittest.main()
else:
pass

但是以上步骤都是数据在代码当中的,假如要测试n个手机号这样的数据,全部写在 @data 装饰器里面就很麻烦,这就引出了数据驱动里面的代码和数据的分离。

3、将数据放入一个文本文件中,从文件读取数据, 如JSON、 excel、 xml、 txt等格式文件 ,这里演示的是json文件类型.

json文件处理, 这个链接介绍了json文件和Python文件基本操作

(1)、在json文件驱动

[
{
“username”: “admin”,
“password”: “123456”
},
{
“username”: “normal”,
“password”: “45678”
}
]

(2)、在测试代码中读取json文件

import json
import unittest
from ddt import ddt, data, unpack

用json多个参数读取

def reads_phone():
with open(‘user.json’, encoding=‘utf-8’) as f:
result = json.load(f) # 列表
return result

@ddt
class TestDemo(unittest.TestCase):

多参数数据驱动

@data(*reads_phone())

unpack 是进行拆包,不然会把列表里面的数据全部传到username这个一个参数,我们要实现列表中的两个数据分别传入对应的变量中

@unpack
def test_2(self, username, password):
print(‘测试二:’, username, password)

if name == ‘main’:
unittest.main()
else:
pass

注意事项:
1、with open里面默认是 ”r“
2、@data 里面的 * 含义是实现每个json对象单个传入方法执行,不然会吧json文件里面所用数据全部传入

  • 是元祖;
    ** 是字典;
    3、参数不能传错,要对应

执行结果:

(3)、txt文件驱动

一行表示一组:

admin,123456
normal,456789

import unittest
def read():
lis = []
with open(‘readtext.txt’, ‘r’, encoding=‘utf-8’) as f:
for line in f.readlines():

lis.append(line) # [‘admin,123456\n’, ‘normal,456789\n’]

lis.append(line.strip(‘\n’)) [‘admin,123456’, ‘normal,456789’] 两个字符串

lis.append(line.strip(‘\n’).split(‘,’)) # [[‘admin’, ‘123456’], [‘normal’, ‘456789’]]
return lis

class TestDome(unittest.TestCase):
def test_01(self):
li = read()
print(li)

if name == ‘main’:
unittest.main()

“”"
split():一个字符串里面用某个字符分割,返回列表
strip():去掉两边的字符或者字符串,默认删除空白符(包括’\n’, ‘\r’, ‘\t’, ’ ')
“”"

(3)、csv 文件驱动

供应商名称,联系人,移动电话
英业达,张三,13261231234
阿里巴巴,李四,13261231231
日立公司,王五,13261231233

写法一:

“”"
编写 csvv.py脚本读取csv中的测试数据
“”"
import csv
class ReadCsv():
def read_csv(self):
lis = []

用csv的API的reader方法!!!!

data = csv.reader(open(‘testdata.csv’, ‘r’)) #!!!
next(data, None)
for line in data:
lis.append(line)

lis.append(line[0]) # 二维数组可以省略行,列不可以省略

lis.append(line[1])

return lis

实例化类

readCsv = ReadCsv()

打印类中的方法

print(readCsv.read_csv())

写法二:推荐

def csvTest():
li = []
with open(‘user.csv’, ‘r’, encoding=‘utf-8’) as f:
filename = csv.reader(f)
next(filename, None)
for r in filename:
li.append®
return li

(4) 、yaml文件驱动

username: admin9
password: 123456

username: normal
password: 789456

对应的json文件

[
{
“username”: “admin9”,
“password”: 123456
},
{
“username”: “normal”,
“password”: 7894
}
]

写法:

“”"
使用yaml数据驱动
“”"

import unittest
from time import sleep

from selenium import webdriver
from ddt import ddt, data, unpack, file_data

@ddt
class YamlTest(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Chrome()
self.driver.get(‘file:///D:/%E6%A1%8C%E9%9D%A2/page/%E6%B3%A8%E5%86%8CA.html’)
self.driver.maximize_window()

def tearDown(self) -> None:
driver = self.driver
sleep(3)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数软件测试工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
img

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

因此收集整理了一份《2024年软件测试全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-Ei96pJ5W-1713001550215)]
[外链图片转存中…(img-JtYgIQSv-1713001550216)]
[外链图片转存中…(img-OfbJQg28-1713001550217)]
[外链图片转存中…(img-EbWySHjT-1713001550218)]
[外链图片转存中…(img-Gh6VCcOc-1713001550218)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上软件测试开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注软件测试)
[外链图片转存中…(img-uGXWSqW3-1713001550219)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值