自动化测试-如何优雅实现方法的依赖

在复杂的测试场景中,常常会存在用例依赖,以一个接口自动化平台为例,依赖关系:

创建用例 --> 创建模块 --> 创建项目 --> 登录。

用例依赖的问题

• 用例的依赖对于的执行顺序有严格的要求,比如让被依赖的方法先执行。

• 一旦使用用例依赖,依赖的用例就无法单独执行了,按照用例的设计原则,每条用例都应该独立执行。

正确的做法

我们应该将依赖的操作封装成方法调用。如果能通过装饰器实现调用,那就很有趣了。

aomaker[1] 提供了这种装饰器的实现,seldom 进行了复刻,只是用法上有所不同。

类内部方法调用

我们可以在测试类下面,创建普通的方法。然后通过@dependent_func()装饰器调用他。

import seldom
from seldom.testdata import get_md5
from seldom.utils import cache, dependent_func


class DependentTest(seldom.TestCase):

    @staticmethod
    def user_login(username, password):
        """
        模拟用户登录,获取登录token
        """
        return get_md5(username+password)

    @dependent_func(user_login, username="tom", password="t123")
    def test_case(self,):
        """
        sample test case
        """
        token = cache.get("user_login")
        print("token", token)


if __name__ == '__main__':
    seldom.main(debug=True)
    cache.clear()

说明

这个例子涉及到不少知识点。

1.test_case() 用例依赖 user_login() 方法,通过 @dependent_func() 装饰器调用 user_login 方法。

2.user_login() 方法运行的时候需要参数(username、password),可以直接在 @dependent_func() 装饰器中设置参数:username=“tom”、 password=“t123”。

3.user_login() 方法运行运行完会生成 token, 保存于 cache中,通过 cache.get() 可以获取到token, 默认通过方法名user_login 作为key获取。

4.为了简化代码,生成token 是通过 get_md5() 根据传入的参数生成的一个 md5 值。

5.cache.clear() 用于清空缓存, 再次调用 user_login() 方法直接不执行,应为cache已经有上次的执行结果了。

执行日志

python zzz_demo.py
...
test_case (zzz_demo.DependentTest.test_case)
sample test case ... 2023-11-15 23:26:36 | INFO     | dependence.py | 🔗 <test_case> depends on <user_login>, execute.
2023-11-15 23:26:36 | INFO     | cache.py | 💾 Set cache data: user_login = 35e0ff9c4cba89998dda8255d0eb5408
2023-11-15 23:26:36 | INFO     | cache.py | 💾 Get cache data: user_login = 35e0ff9c4cba89998dda8255d0eb5408
token 35e0ff9c4cba89998dda8255d0eb5408
ok

----------------------------------------------------------------------
Ran 1 test in 0.005s

OK
2023-11-15 23:26:36 | SUCCESS  | runner.py | A run the test in debug mode without generating HTML report!
2023-11-15 23:26:36 | INFO     | cache.py | 💾 Clear all cache data

外部类方法依赖

•创建依赖方法

# common.py
from seldom.testdata import get_md5


class Login:

    @staticmethod
    def account_login(username, password):
        """
        模拟用户&密码登录,获取登录token
        """
        return get_md5(username+password)


login=Login()

•用例引用依赖方法

import seldom
from seldom.utils import cache, dependent_func
from common import Login # 方式1:引用依赖类
# from common import login  # 方式2:引用初始化好的类对象


class DependentTest(seldom.TestCase):


    @dependent_func(Login().account_login, key_name="token1", username="tom", password="t123")
    # @dependent_func(login.account_login, key_name="token1", username="tom", password="t123")
    def test_case(self):
        """
        Used tuple test data
        """
        token = cache.get("token1")
        print("token", token)


if __name__ == '__main__':
    seldom.main(debug=True)

说明

1.Common 类的account_login()方法可以不设置为静态方法,导入时需要类需要加括号:Common().user_login。 或者先初始化类对象login=Login() 再调用。

2.key_name 指定缓存的 key,如果指定为token1, 从缓存读取也使用这个cache.get(“token1”)。

多重方法依赖

复杂的场景当然是需要多重依赖的。

1.被依赖的方法可以进一步使用 dependent_func()装饰器进行多重复依赖。

查询模块 --> 查询项目 --> 登录

# common.py
from seldom.testdata import get_md5, get_int
from seldom.utils import cache, dependent_func

class Login:

    @staticmethod
    def account_login(username, password):
        """
        模拟用户&密码登录,获取登录token
        """
        return get_md5(username+password)

class DepFunc:

    @staticmethod
    @dependent_func(Login.account_login, key_name="token", username="jack", password="456")
    def get_project_id():
        token = cache.get("token")
        print(f"使用token:{token} 查询项目, 返回项目ID")
        return get_int(1, 1000)


    @staticmethod
    @dependent_func(get_project_id, key_name="pid")
    def get_module_id():
        pid = cache.get("pid")
        print(f"使用项目ID:{pid} 查询模块, 返回模块ID")
        return get_int(1, 1000)

在用例中直接调用 DepFunc.get_module_id 方法即可。

import seldom
from seldom.utils import cache, dependent_func
from common import DepFunc


class DependentTest(seldom.TestCase):


    @dependent_func(DepFunc.get_module_id, key_name="mid")
    def test_case(self):
        """
        sample test case
        """
        mid = cache.get("mid")
        print(f"模块ID: {mid}")


if __name__ == '__main__':
    seldom.main(debug=True)
    cache.clear()

2.测试用例也可以同时使用多个 @dependent_func() 装饰器依赖多个方法,顺序由上到下执行,这种方式主要用于被依赖的方法之间没有依赖关系

# common.py
from seldom.testdata import get_int, username


class DataFunc:

    @staticmethod
    def get_name():
        return username(language="zh")

    @staticmethod
    def get_age():
        return get_int(1, 99)

在用例中使用多个@dependent_func()依赖装饰器。

import seldom
from seldom.utils import cache, dependent_func
from common import DataFunc


class DependentTest(seldom.TestCase):


    @dependent_func(DataFunc.get_name, key_name="name")
    @dependent_func(DataFunc.get_age, key_name="age")
    def test_case(self):
        """
        sample test case
        """
        name = cache.get("name")
        age = cache.get("age")
        print(f"名字: {name}, 年龄: {age}")


if __name__ == '__main__':
    seldom.main(debug=True)
    cache.clear()

参数化使用

参数化 @data()、 @file_data() 是seldom最重要的功能之一,能否和 @dependent_func() 一起使用? 当然可以。

import seldom
from seldom import data
from seldom.testdata import get_md5
from seldom.utils import cache, dependent_func


class DependentTest(seldom.TestCase):

    @staticmethod
    def user_login(username, password):
        """
        模拟用户登录,获取登录token
        """
        return get_md5(username+password)

    @data([
        ("case1", "foo"),
        ("case2", "bar"),
    ])
    @dependent_func(user_login, username="tom", password="t123")
    def test_case(self, _, keyword):
        """
        Used tuple test data
        """
        token = cache.get("user_login")
        print(keyword, "token", token)


if __name__ == '__main__':
    seldom.main(debug=True)
    cache.clear()

说明

1.@data() 装饰器必须写在 @dependent_func() 的上面。

2.运行两条用例,user_login() 被执行过一次后,第二次则不需要重复执行,直接返回结果。

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:


这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取   

 

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值