当前位置: 首页 > 面试题库 >

模拟一系列相互依赖的调用

臧威
2023-03-14
问题内容

我有一种方法可以抓取网页并将数据保存到文件中(请参见下面的示例代码)。我需要测试结果数据是否格式正确。

问题是,数据是从一系列调用中接收到的,并且进一步的调用使用了先前调用的结果。更糟糕的是,许多涉及的调用都是在具有不同参数的相同对象(a
Webdriver,a WebDriverWaitexpected_conditions模块)上完成的。

我看到
unittest.mock.Mock可以模拟一个简单调用或一系列简单调用的结果,但是看不到如何实现像这样纠缠的东西。我看到的唯一方法是手动重新实现该方法进行的每个调用,并将我在该方法中传递的参数复制到那些实现中,以便它们知道每次调用返回什么。并针对其他所有测试用例再次执行此操作。这听起来像是编写和维护的绝对噩梦:代码比测试本身多几倍,并且与代码的复制比例接近1:1。因此,我拒绝继续进行操作,直到有人告诉我有更好的方法或证明没有更好的方法,并且每个人都真的这样做(我不相信),例如每次页面上的标签更改时都会重写所有测试(这是一个实现细节,因此通常不应该

示例代码(适用于http://example.com):

import selenium.webdriver
from selenium.webdriver.common.by import By as by
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


def dump_accreditation_data(d, w, i, path):
    f = codecs.open(os.path.join(path, "%d.txt" % i), "w", encoding="utf-8")

    u = u'http://example.com/%s/accreditation' % i
    d.get(u)

    # page load
    w.until(EC.visibility_of_element_located((by.XPATH,"//p")))    #the real code has a more complex expression here with national characters
    w.until_not(EC.visibility_of_element_located((by.CSS_SELECTOR, '.waiter')))
    print >> f, u

    # organization name
    e = w.until(EC.visibility_of_element_located((
        by.CSS_SELECTOR, 'h1'
    )))
    org_name = e.text
    print >> f, org_name
    del e

    #etc
    e = d.find_element_by_xpath(u'//a[text()="More information..."')
    print >> f, e.get_attribute('href')

#How it's supposed to be used:
d = selenium.webdriver.Firefox()
w = WebDriverWait(d, 10)
dump_accreditation_data(d, w, 123, "<output_path>")

问题答案:

我同意,就目前的代码而言,对您描述的方式进行单元测试没有多大意义。但是,这不只是因为要进行大量工作:测试的目标当然是在代码中发现错误。单元测试的目的是发现那些可以在隔离单元中发现的错误。但是,示例代码的很大一部分与与外部库的交互有关。

在算法级别上,几乎没有代码,例如:

os.path.join(path, "%d.txt" % i)

要么

u = u'http://example.com/%s/accreditation' % i

或创建输出文件内容。

也就是说,如果代码中存在错误,则它们很可能处于交互级别:使用正确的参数以正确的顺序,正确的格式的参数等调用正确的库函数-
使用库的模拟,但是,您不会发现交互错误,因为模拟是您实现的,并且只会反映您(可能是错误的)对库行为的理解。

我对测试此代码的建议是:将算法代码与与库进行交互的代码分开。例如,您可以创建小的辅助函数来计算输出文件名和输入URL。您可以在代码的交互主导部分中,从网页中提取所有数据,然后(在单独的功能中)使用所有这些数据创建输出文件内容。

然后可以使用单元测试来测试所有这些辅助功能。您将使用集成测试来测试的其余功能。



 类似资料:
  • 问题内容: 我已经搜索了很多,但是我发现的主要是python中的递归编程示例。因此,问题来了: 我该如何实现? 问题答案: 一切在Python中都是动态的-甚至是类声明。在初始声明之后,没有什么可以阻止您修改类的内容的: 注意:如果您不太熟悉Python,则该关键字仅允许您说“这里什么都没有”-除非A类的空值与本例中的一样空,否则它并不重要!

  • 我有一个多模块Maven项目,其中包含子模块ModuleA和ModuleB等。ModuleA将ModuleB列为依赖项。但是,当仅构建模块A时,Maven不会解决模块B的依赖关系-导致。我想避免构建整个父级以使构建更快。目前我发现让它工作的唯一方法是使用exec插件和脚本,将父项目称为“ModuleB, ModuleA”,这意味着我必须在每次依赖项更改时更改脚本(例如添加ModuleC)。 是否有

  • 我有两个服务组件:PromiseService。服务ts(处理延迟调用和异步调用) 和员工ervice.service.ts(处理员工信息) 但是,我得到了以下错误: 检测到循环依赖关系:员工ervice.service.ts- 我试图更改Promise Service组件并删除以下行: 但是,出现了另一个错误:未处理的promise拒绝:无法读取未定义的属性“updateid”;区域:;任务:p

  • 问题内容: 我有一个在后端使用postgres数据库的项目,并且我正在创建一个Dockerfile,该文件可以自动设置数据库的本地开发实例。该数据库包含大量功能,并且这些功能在历史上一直存储在上下文相关的sql文件中,例如,users.sql,companys.sql。这样做很好,因为每当进行更改时,我都可以简单地执行所有视图和删除/重新创建所有函数的相关sql文件。 但是,当尝试在一个新的pos

  • Blue使用Maven插件构建适当的工件: 如果我在Blue上运行任务,它会创建一个JAR和一个POM,并将它们放在我的中,没有问题。 我将Blue的导入到我的IDEA项目中,它为Blue创建了一个模块,同样没有问题。 编辑添加:多模块实际上不是一个选项,因为有问题的依赖关系在多个应用程序项目之间共享(更不用说其他共享库项目了),并且不能整齐地放入一个层次结构的目录结构中。 编辑添加:有关我最终得

  • 我对阿帕奇骆驼很陌生。我们需要同时处理多个动态的路由生命周期。 “等待,因为仍有2个飞行和挂起的交换要完成,超时300秒。”-此消息继续 没有打印任何内容,但B不工作(没有日志,没有任何内容)