Py.test - 将变量从 csv 应用到装饰器?

dw1*_*919 3 python testing selenium pytest testrail

当我试图解释我的困境时,请耐心等待,我仍然是一个 Python 新手,所以我的术语可能不正确。另外,我对这篇文章不可避免的冗长感到抱歉,但我会尽力解释尽可能多的相关细节。

快速概述:

我目前正在使用 py.test 为一组功能基本相同的网站开发一套 Selenium 测试

我的一个典型测试如下所示:

@pytestrail.case('C100123')  # associates the function with the relevant TR case
@pytest.mark.usefixtures()
def test_login():
   # test code goes here
Run Code Online (Sandbox Code Playgroud)

正如我之前提到的,我的目标是创建一组代码来处理具有(几乎)相同功能的许多网站,因此上面示例中的硬编码装饰器将不起作用。

我尝试了一种数据驱动方法,其中包含 csv 以及 TestRail 中的测试列表及其案例 ID。

例子:

website1.csv:
Case ID | Test name
C100123 | test_login


website2.csv:
Case ID | Test name
C222123 | test_login
Run Code Online (Sandbox Code Playgroud)

我编写的代码将使用检查模块来查找正在运行的测试的名称,找到相关的测试 ID 并将其放入名为 test_id 的变量中:

import csv
import inspect
class trp(object):
def __init__(self):
    pass


with open(testcsv) as f:  # testcsv could be website1.csv or website2.csv
    reader = csv.reader(f)
    next(reader)  # skip header
    tests = [r for r in reader]


def gettestcase(self):
    self.current_test = inspect.stack()[3][3]
    for row in trp.tests:
        if self.current_test == row[2]:
            self.test_id = (row[0])
            print(self.test_id)
            return self.test_id, self.current_test


def gettestid(self):
    self.gettestcase()
Run Code Online (Sandbox Code Playgroud)

这个想法是装饰器会根据我当时使用的 csv 动态变化。

@pytestrail.case(test_id)  # now a variable
@pytest.mark.usefixtures()
def test_login():
   trp.gettestid()
   # test code goes here
Run Code Online (Sandbox Code Playgroud)

因此,如果我为 website1 运行test_login,装饰器将如下所示:

@pytestrail.case('C100123')
Run Code Online (Sandbox Code Playgroud)

如果我为 website2 运行test_login装饰器将是:

@pytestrail.case('C222123')
Run Code Online (Sandbox Code Playgroud)

我为自己想出这个解决方案感到非常自豪,并尝试了一下……但没有成功。虽然代码本身可以工作,但我会得到一个异常,因为 test_id 未定义(我明白为什么 -gettestcase在装饰器之后执行,所以它当然会崩溃。

我可以处理此问题的唯一其他方法是在执行任何测试代码之前应用 csv 和 testID 。我的问题是 - 我如何知道如何将测试与其测试 ID 关联起来?一个优雅的、最小的解决方案是什么?

抱歉问了这么长的问题。如果您需要更多解释,我会密切关注并回答任何问题。

hoe*_*ing 6

pytest非常擅长为测试进行各种元编程工作。如果我正确理解你的问题,下面的代码将用pytestrail.case标记进行动态测试标记。在项目根目录中,创建一个名为的文件conftest.py并将以下代码放入其中:

import csv
from pytest_testrail.plugin import pytestrail


with open('website1.csv') as f:
    reader = csv.reader(f)
    next(reader)
    tests = [r for r in reader]


def pytest_collection_modifyitems(items):
    for item in items:
        for testid, testname in tests:
            if item.name == testname:
                item.add_marker(pytestrail.case(testid))
Run Code Online (Sandbox Code Playgroud)

现在您根本不需要标记测试@pytestrail.case()- 只需编写其余代码即可pytest处理标记:

def test_login():
    assert True
Run Code Online (Sandbox Code Playgroud)

启动时pytest,上面的代码将读取website1.csv并存储测试 ID 和名称,就像您在代码中所做的那样。在测试运行开始之前,pytest_collection_modifyitemshook 将执行,分析收集的测试 - 如果测试与 csv 文件中的名称相同,pytest则会pytestrail.case向其中添加带有测试 ID 的标记。