使用“数据驱动测试”之前

栏目: 编程工具 · 发布时间: 5年前

内容简介:什么是数据驱动测试?从它的定义来看,就是数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变。说的直白些,就是参数化的应用。
编辑推荐:
本文来自cnblogs,文章简单明了的给大家介绍了什么是数据驱动测试,然后借助单元测试框架怎么做自动化测试。

什么是数据驱动测试?

从它的定义来看,就是数据的改变从而驱动自动化测试的执行,最终引起测试结果的改变。说的直白些,就是参数化的应用。

使用“数据驱动测试”之前

“他们”认为数据驱动什么样子?

这里以csv文件为例,大多文章也是选用的csv/excel文件。

参数、断言、结果都有了,大概就这样子吧?

接下来需要将数据读取出来。

# coding=utf-8

import csv

import codecs

# 读取本地 CSV 文件

data = csv.reader(codecs.open('user_info.csv', 'r', 'utf_8_sig'))

# 用户存放用户数据

users = []

# 循环输出每一行信息

for line in islice(data, 1, None):

users.append(line)

# 打印

print(users)

得到结果:

 [['', '123', '请输入帐号', ''],
 ['user', '', '请输入密码', ''],
 ['error', 'error', '帐号或密码错误',''],
 ['admin', 'admin123', 'admin你好', ''],
 ['guest', 'guest123', 'guest你好', '']]

这里得到一个测试数据的二维数组。

那么接下来要用这些数据做自动化测试了?被测试功能如下:

使用“数据驱动测试”之前

测试代码如下:

# 测试登陆功能

from selenium import webdriver

driver = webdriver.Chrome()

for user in users:

driver.get("http://127.0.0.1:8000/")

driver.find_element_by_id ("inputUsername").send_keys (user[0])

driver.find_element_by_id ("inputPassword").send_keys (user[1])

driver.find_element_by_id ("Login").click()

sleep(2)

tips = driver.find_element_by_id("tips").text

print(tips)

print(user[2])

try:

assert tips == user[2]

except AssertionError as msg:

print(msg)

user[3] = "Faile"

else:

user[3] = "Pass"

driver.quit()

# 打印结果

print(users)

运行之后的测试结果:

 [['', '123', '请输入帐号', 'Pass'],
 ['user', '', '请输入密码', 'Pass'],
 ['error', 'error', '帐号或密码错误','Pass'],
 ['admin', 'admin123', 'admin你好', 'Faile'],
 ['guest', 'guest123', 'guest你好', 'Faile']]

看,结果已经写到最后一列了。

最后,我们还需要将测试结果写回到csv文件中。

# 读取本地 CSV 文件

csv_file = csv.writer(codecs.open('user_info.csv', 'w','utf_8_sig'),

# 写入标题

csv_file.writerow(['用户名','密码','断言','结果'])

# 循环写入数据

for user in users:

csv_file.writerow(user)

# 打印

print(users)

打开CSV文件,结果如下:

使用“数据驱动测试”之前

看结果一列,是不是已经有了结果。

那么,下来思考几个问题。

1、测试结果是否太过简单了,只有“Pass”和“Faile”,没有任何失败的日志,是否需要另起一列记录失败日志?

2、如何统计出总失败的用例数和成功的用例数?

3、如果想单独验证失败的两条用例应该怎么做?例如上图中的最后两条失败的用例。

4、上面的测试代码中,有多少是真正用在测试操作的,至少一半都在读写csv文件,是否需要做封装,想想怎么封装更简单?

5、在获取具体读取数据的时候,我们使用的是user[0]、user[1]、user[2],你真的容易分辨这些数据么?如果又加了一列数据呢?不改代码是不是就对不上号了。

6、这只是一组登录数据。我们知道不同的功能,所需要的数据是不一样的,比如搜索,只需要“搜索关键字”, 例如注册,需要“邮箱”、“密码”、“重复密码”、“昵称”等。我们一个系统有N多功能的好吧!

7、如第6条,这些测试数据要怎么放,放在一个csv文件还是多个文件?怎么统计测试结果?

所以,知道读取数据文件有多坑了吧!?谁说的方便维护?你一定没用这种方式写过真正的项目吧!一直处在跟着别人写demo阶段。如果你有更“高大上”的处理方式欢迎请告诉我,谢谢!

以下,我将介绍基于单元测试框架的数据驱动。

单纯读取数据文件来做自动化是有诸多问题的。那么我们借助单元测试框架来做自动化就爽多了,因为它解决了测试中的几问题。

如何定义一条测试用例,我们知道编程的世界里并没“用例”的概念。它只有目录、文件、类、方法、函数...,而单元测试框架告诉我们如何定义一条用例。

如何写断言,是的!当你做了一堆操作之后,如何判断这一系列操作是符合预期的,那么一定要拿实际结果与预期结果进行比较,而单元测试框架告诉我们如何写断言。

测试结果统计,当执行了一系列的用例之后,总共运行了多少条用例,成功了多少条,失败了多少条,失败的用例错误在哪里?单元测试框架会帮我们统计和展示。

被测功能还是上文的功能。

使用“数据驱动测试”之前

这里以unittest 单元测试框架为例。

import unittest

from selenium import webdriver

class LoginTest(unittest.TestCase):

@classmethod

def setUpClass(cls):

cls.driver = webdriver.Chrome()

cls.url = "http://127.0.0.1:8000/"

cls.driver.implicitly_wait(10)

@classmethod

def tearDownClass(cls):

cls.driver.quit()

def user_login (self, username, password):

driver = self.driver

driver.get(self.url)

driver.find_element_by_id ("inputUsername ").send_keys (username)

driver.find_element_by_id ("inputPassword ").send_keys (password)

driver.find_element_by_id ("Login ").click()

def atest_login_01(self):

self.user_login("", '123')

tips = self.driver.find_element_by_id ("tips").text

self.assertEqual(tips, '请输入帐号')

def atest_login_02(self):

self.user_login ("user", "")

tips = self.driver.find_element_by_id ("tips").text

self.assertEqual(tips, '请输入密码')

def atest_login_03(self):

self.user_login("error", "error")

tips = self.driver.find_element_by_id ("tips").text

self.assertEqual (tips, '帐号或密码错误')

def atest_login_04(self):

self.user_login ("admin", " admin123456")

sleep(2)

tips = self.driver.find_element_by_id ("user").text

self.assertEqual (tips, 'admin你好')

if __name__ == '__main__':

unittest.main()

看!测试代码是不是非常清晰。运行结果如下。

...F

=============================

FAIL: test_login_04 (__main__.LoginTest)

-------------------------------

Traceback (most recent call last):

File "test_login.py", line 43, in test_login_04

self.assertEqual(tips, 'admin你好')

AssertionError: 'admin' != 'admin你好'

- admin

+ admin你好

-----------------------------

Ran 4 tests in 12.977s

FAILED (failures=1)

结果告诉我们运行了4条测试,1条失败了,失败的原因是test_login_04用例断言预期结果为“admin你好”,实际结果为“admin”。

可是,这没有用到读取数据文件啊?不是,数据驱动啊? 我以为这么规范的编写测试用例,要啥自行车。

其实,我已经尽量的把登录操作做了封装,每条用例里面只关心登录的数据和结果的断言。谁告诉你“数据驱动”就必须要“读取数据文件”的?

我们继续引入unitest的参数化。

import unittest

from selenium import webdriver

from time import sleep

class LoginTest(unittest.TestCase):

@classmethod

def setUpClass(cls):

cls.driver = webdriver.Chrome()

cls.url = "http://127.0.0.1:8000/"

cls.driver.implicitly_wait(10)

@classmethod

def tearDownClass(cls):

cls.driver.quit()

def user_login(self, username, password):

driver = self.driver

driver.get(self.url)

driver.find_element_by_id ("inputUsername").send_keys (username)

driver.find_element_by_id ("inputPassword").send_keys (password)

driver.find_element_by_id ("Login").click()

@parameterized.expand([

("user_null", '', "123", "请输入帐号"),

("pawd_null", "user", '', "请输入密码"),

("login_error", "error", "error", "帐号或密码错误"),

("login_success", "admin", "admin123456", "admin你好"),

])

def test_login (self, name, username, password, assert_text):

self.user_login(username, password)

if name == "login_success":

sleep(2)

tips = self.driver.find_element_by_id ("user").text

self.assertEqual(tips, assert_text)

else:

tips = self.driver.find_element_by_id ("tips").text

self.assertEqual(tips, assert_text)

if __name__ == '__main__':

unittest.main(verbosity=2)

反正都是定义测试数据,这里提供了规范的元组给你用来定义数据,而且测试数据与测试方法上下呼应,维护起来也比读取文件方便多了,这次还要啥自行车?

测试结果:

test_login_0_user_null (__main__.LoginTest) ... ok

test_login_1_pawd_null (__main__.LoginTest) ... ok

test_login_2_login_error (__main__.LoginTest) ... ok

==============================

FAIL: test_login_3_login_success (__main__.LoginTest)

---------------------------------

Traceback (most recent call last):

File "C:\Python36\lib\site-packages\parameterized-0.6.1-py3.6.egg\parameterized\parameterized.py", line 392, in standalone_func

return func(*(a + p.args), **p.kwargs)

File "test_login.py", line 37, in test_login

self.assertEqual(tips, assert_text)

AssertionError: 'admin' != '请输入密码'

- admin

+ 请输入密码

------------------------------------

Ran 4 tests in 12.363s

FAILED (failures=1)

测试结果依然清晰明白。

这个话题,本来到此就结束了,我其实是很鄙视读取数据文件的操作的,因为真get不到它的“方便”之处,做自动化测试写代码就老老实实的写代码,就你测试用的这点数据,真没必要读取文件,数据库就更谈不上了。但是,那么多人都在分享读取数据文件的demo(实际规模化之后就不得而知了),我也看了不少资料,找到一些勉强能接受的方法。

当然,这又是另一篇文章了。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

C语言的科学和艺术

C语言的科学和艺术

罗伯茨 / 翁惠玉 / 机械工业出版社 / 2005-3 / 55.00元

《C语言的科学和艺术》是计算机科学的经典教材,介绍了计算机科学的基础知识和程序设计的专门知识。《C语言的科学和艺术》以介绍ANSI C为主线,不仅涵盖C语言的基本知识,而且介绍了软件工程技术以及如何应用良好的程序设计风格进行开发等内容。《C语言的科学和艺术》采用了库函数的方法,强调抽象的原则,详细阐述了库和模块化开发。此外,《C语言的科学和艺术》还利用大量实例讲述解决问题的全过程,对开发过程中常见......一起来看看 《C语言的科学和艺术》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器