首页 > 解决方案 > 如何测试使用请求的复杂功能?

问题描述

我想测试基于其他人创建的 API 的代码,但我不确定我应该怎么做。

我创建了一些函数来将 json 保存到文件中,因此我不需要每次运行测试时都发送请求,但是我不知道如何在原始(检查)函数接受输入 arg 的情况下使其工作(problem_report) 是 API 提供的某个类的一个实例,它有这个 issue_report.get_correction(corr_link)方法。我只是想知道这是否是我编写错误代码的标志,因为我无法为此编写测试,或者我应该在我的测试文件中重写这个函数,就像我在下面提供的代码末尾显示的那样。

# I to want test this function
def check(problem_report): 
    corrections = {}
    for corr_link, corr_id in problem_report.links.items():
        if re.findall(pattern='detailCorrection', string=corr_link):
            correction = problem_report.get_correction(corr_link)
            corrections.update({corr_id: correction})
    return corrections

# function serves to load json from file, normally it is downloaded by API from some page.
def load_pr(pr_id): 
    print('loading')
    with open('{}{}_view_pr.json'.format(saved_prs_path, pr_id)) as view_pr:
        view_pr = json.load(view_pr)
    ...
    pr_info = {'view_pr': view_pr, ...}
    return pr_info

# create an instance of class MyPR which takes json to __init__
@pytest.fixture
def setup_pr():
    print('setup')
    pr = load_pr('123')
    my_pr = MyPR(pr['view_pr'])
    return my_pr 

# test function
def test_check(setup_pr):
    pr = setup_pr
    checked_pr = pr.check(setup_rft[1]['problem_report_pr'])
    assert checker_pr

# rewritten check function in test file 
@mock.patch('problem_report.get_correction', side_effect=get_corr)
def test_check(problem_report):
    corrections = {}
    for corr_link, corr_id in problem_report.links.items():
        if re.findall(pattern='detailCorrection', string=corr_link):
            correction = problem_report.get_correction(corr_link)
            corrections.update({corr_id: correction})
    return corrections

我不确定我是否提供了足够的代码和解释来理解问题,但我希望如此。我希望你能告诉我这是否正常,某些函数很难测试,如果这是单独重写它们的好习惯,那么我可以在测试函数中模拟函数。我还想我可以编写具有类似功能的新类,但 API 非常大,而且过程会很长。

标签: pythonpython-3.xunit-testingpytest

解决方案


我对您的问题的理解如下:您有一个check您认为难以测试的功能,因为它依赖于problem_report. 为了使其更好地可测试,您已将代码复制到测试文件中。您将测试复制的代码,因为您可以将其修改为更易于测试。而且,您想知道这种方法是否有意义。

答案是否定的,这没有意义。您不是在测试真正的功能,而是完全不同的代码。好吧,代码可能不会开始完全不同,但在短时间内副本和原件会出现偏差,确保副本始终与原件相似将是维护的噩梦。改进代码的可测试性是另一回事:您可以对check函数进行更改以提高其可测试性。但是,在测试和生产代码中都应该使用完全相同的结果函数。

那么如何更好地测试功能check呢?首先,您确定使用原始problem_report对象真的不能在您的测试中合理使用吗?(这里有一些标准可以帮助您决定:python 测试用例要模拟什么?)。现在,让我们假设您得出的结论是您不能明智地使用原始problem_report.

在这种情况下,这里的接口很简单,可以定义一个 mocked problem_report。请记住,Python 使用鸭子类型,因此您只需创建一个具有成员的类,该links成员具有items()方法。另外,您的模拟problem_report类需要一个方法get_correction()。除此之外,您的模拟不必生成与problem_report. 该items()方法可以简单地返回一个列表列表,例如[["a",2],["xxxxdetailCorrectionxxxx",4]]. 相同的参数适用于get_correction,例如,它可以简单地返回它的参数或派生值,比如它的负数。

对于上面的示例(items()返回[["a",2],["xxxxdetailCorrectionxxxx",4]]get_correction返回其参数的负数),预期结果将是{4: -4}. 无需模拟真实correction物体。而且,您可以创建您的模拟版本,problem_report而无需从文件中读取数据 - 模拟可以完全从单元测试代码中设置。


推荐阅读