使用“数据驱动测试”之前你应该知道的(终极篇)

2018-08-29  本文已影响0人  虫师2017

这周我们继续这个系列,这是最后一篇。建议先阅读前两篇文章。

使用“数据驱动测试”之前应该知道的

使用“数据驱动测试”之前你应该知道的(二)

其实,我以前一直按照第二篇文章所介绍的方式写用例,写过UI自动化(200+用例),也写接口自动化用例(500+用例),接口自动化第一版是用PHP写的,当时还没用到参数化,第二版用python重写才用到了parameterized做参数化,结果大大缩减了测试代码的行数。我不认为把接口参数写到用例里有什么不妥。因为接口测试有数据的初始化动作,所以,接口用例很稳定,只要用例失败一准是接口处理逻辑变动了,接口自动化项目被我维护了两年,直到后来离职。之所以说这些,只是想说明我的观点至少不是写两个demo总结出来的。

直到最近,我在亚马逊上看到一本书《Selenium Framework Design in Data Driven Testing》,评价挺高,经过一翻查找,有同学将这本书第十章的例子放到了GitHub上。
https://github.com/PacktPublishing/Selenium-Framework-Design-in-Data-Driven-Testing

整本书基于Java语言,基于TestNG单元测试框架的DataProvider来实现读JSON数据文件。所以,读数据文件是不能脱离单元测试框讨论的,因为它确实解决了用代码写测试用例的大部分问题。

既然这样,那python下面的单元测试框架unittest/pytest是否也有类似的操作,不用那么麻烦就可以把文件中的数据读出来并参数化到测试用例中。
同样以登录功能为例,这里将介绍支持unittest的ddt库。

图片1.png

首先创建一个数据文件:test_ddt_file.json

{
    "test_login_01":{
        "username":"",
        "password":"123",
        "assert_text": "请输入帐号"
    },
    "test_login_02":{
        "username":"user",
        "password":"",
        "assert_text": "请输入密码"
    },
    "test_login_03":{
        "username":"error",
        "password":"error",
        "assert_text": "帐号或密码错误"
    },
    "test_login_04":{
        "username":"admin",
        "password":"admin123456",
        "assert_text": "admin你好"
    }
}

创建测试用例:

import unittest
from selenium import webdriver
from ddt import ddt, file_data
from time import sleep


@ddt
class TestLogin(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()

    @file_data("./test_ddt_file.json")
    def test_login(self, username, password, assert_text):
        self.user_login(username, password)
        if username == "admin":
            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()

注意看文件的读取,只需要通过@file_data装饰器指定数据文件的路径就好。只能方便到这种程度了。那么这是不是就是完美的了?

首先,一个测试文件只能放一种类型的数据。

"test_one": [1, 2, 3],
"test_two": "split",
"test_three": {"three": 3},
"test_four": {"four": 4, "five": 5}

上面这种格式的数据肯定是不行的,因它们的数据格式是不一致。所以,我们要分四个文件分别存放这四条用例数据。

难道要自动化的项目只有登录么?肯定不是,不同的功能点用到的数据是不一样的。

你需要为每一个涉及到数据的功能点创建一个数据文件。如果系统有50个这样的功能呢!需要创建50个数据文件。当需要维护用例的时候,你需要分两步,第一步先找到用例代码,然后,再根据名称找到对应的数据文件增加或删除一条用例,再切会到用例代码使其运行通过...

……

@data(["", "123", "请输入帐号"],
      ["user", "", "请输入密码"],
      ["error", "error", "帐号或密码错误"],
      ["admin", "admin123456", "admin你好"],
)
def test_login_2(self, username, password, assert_text):
    self.user_login(username, password)
    if username == "admin":
        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)
……

为何不把数据和用例绑定在一起,这样不管是改用例,还是改数据都是一目了然的事情。

本文写作的是带有一些个人情绪在里面的,因为我看到那些上来就教测试新手读取excel文件的,甚至把用例都写到excel文件的行为是不认同的。

图片2.png

这玩意,你做的有QTP专业么?QTP的份额还不是在下滑。开源的 robot Framework已经封装的那么好了,过了那个风口,现在还不是不温不火。因为业务场景是复杂多变的,前端开发技术的更新,也会倒逼自动化技术的演变。不然,功能测试人员早被自动化测试取代了。

要想把自动化技术做好,好老老实实的锻炼自己的编程技术,从设计模式,代码架构,方法封装几个方面把你的自动化化测试项目做的足够灵活和可维护。

别整天跟风,看到别的测试人员随便封装了所谓的“测试框架”,你就好奇心爆棚的学两下,写两个demo,然后就丢一边了。

难道不应该潜下心好好分析自己测试的业务,哪些适合做UI,哪些适合做接口,哪些适合写一些脚本,或做一个系统来提高测试效率。

上一篇文章有人说,我作为一个公众号不应该用“鄙视”这样不友善的词,那这里声明一个,虫师所有文章仅代表他个人观点,你们不认同可以喷他,与“测试圈TC”公众号无关。

上一篇 下一篇

猜你喜欢

热点阅读