单元测试屏刮板

时间:2009-08-10 17:17:59

标签: c# unit-testing tdd screen-scraping

我正在编写HTML屏幕抓取工具。为此创建单元测试的最佳方法是什么?

拥有静态html文件并在每次测试时从磁盘读取它是否“没问题”?

你有什么建议吗?

11 个答案:

答案 0 :(得分:3)

为了保证测试可以一遍又一遍地运行,您应该有一个静态页面来测试。 (即从磁盘上可以)

如果您编写的测试涉及Web上的实时页面,那可能不是单元测试,而是集成测试。你也可以拥有它们。

答案 1 :(得分:3)

文件还可以,但是:您的屏幕抓取工具处理文本。您应该进行各种单元测试,以“刮擦”每个单元测试中硬编码的不同文本片段。每件作品都应“激发”刮刀方法的各个部分。

通过这种方式,您可以完全删除对外部文件和网页的依赖关系。而且您的测试将更容易单独维护,因为它们不再依赖于外部文件。您的单元测试也会(稍微)更快地执行;)

答案 2 :(得分:3)

对于我的ruby + mechanize scraper,我一直在尝试使用集成测试来尽可能透明地测试尽可能多的目标页面版本。

在测试中,除了手动保存的“原始”副本之外,我正在重载刮刀HTTP提取方法以自动重新缓存新版本的页面。然后每个集成测试运行:

  • 原始手动保存的页面(有点像单元测试)
  • 我们所拥有的最新版本
  • 现在来自网站的实时副本(如果离线则会跳过)

...如果它们返回的字段数不同,则会引发异常,例如:他们已经更改了缩略图类的名称,但仍然提供了一些抵御测试的弹性,因为目标站点已关闭。

答案 3 :(得分:2)

创建您的单元测试,您需要知道您的刮刀如何工作以及您认为应该提取哪些类型的信息。根据刮刀的复杂程度,使用简单的网页作为单元测试可能没问题。

对于回归测试,您绝对应该将文件保存在磁盘上。

但如果您的最终目标是抓住网络,那么您还应该记录常见查询和返回的HTML。这样,当您的应用程序失败时,您可以快速捕获所有过去感兴趣的查询(使用说wgetcurl),并找出HTML是否以及如何更改。

换句话说,回归测试针对已知HTML和来自已知查询的未知HTML。如果您发出已知查询并且返回的HTML与数据库中的HTML相同,则无需对其进行两次测试。

顺便说一下,自从我停止尝试抓取原始HTML并开始刮取w3m -dump的输出时,我已经很多更好的运气屏幕抓取,这是ASCII,所以更容易处理!

答案 4 :(得分:2)

你需要考虑你正在抓什么。

  • 静态Html(不一定会大幅改变并破坏你的刮刀的html)
  • 动态Html(松散术语,可能会彻底改变的html)
  • 未知(从中提取特定数据的html,无论格式如何)

如果html是静态的,那么我只会在磁盘上使用几个不同的本地副本。既然你知道html不会大幅改变并且破坏你的刮刀,你可以自信地使用本地文件编写测试。

如果html是动态的(再次,松散的术语),那么您可能希望继续在测试中使用实时请求。如果您在此方案中使用本地副本并且测试通过,您可能希望实时html执行相同操作,但它可能会失败。在这种情况下,通过每次测试实时html,您可以在部署之前立即知道您的屏幕刮刀是否符合标准。

现在,如果您根本不关心html的格式,元素的顺序或结构,因为您只是根据某些匹配机制(正则表达式/其他)拉出单个元素,那么本地副本可能没问题,但你可能仍然希望倾向于对现场HTML进行测试。如果实时html发生了变化,特别是你正在寻找的部分内容,那么如果你使用本地副本,你的测试可能会通过,但部署可能会失败。

如果可以,我的意见是测试实时HTML。当live html可能失败时,这将阻止您的本地测试通过,反之亦然。我不认为屏幕分析器是最好的做法,因为屏幕分析器本身就是不寻常的小虫子。如果网站或Web服务没有公开API,那么使用screenscraper就可以获得所需的数据。

答案 5 :(得分:1)

你的建议听起来很明智。我可能有一个合适的测试HTML文件目录,以及每个文件的预期数据。当您遇到有问题的页面时,您可以进一步填充它,以形成完整的回归测试套件。

您还应该执行集成测试以实际谈论HTTP(不仅包括成功的页面提取,还包括404错误,无响应的服务器等)。

答案 6 :(得分:1)

我想说这取决于您需要运行多少次不同的测试。

如果您需要在单元测试中检查大量不同的内容,最好在测试初始化​​过程中生成HTML输出。它仍然是基于文件的,但你会有一个可扩展的模式:

Initialize HTML file with fragments for Test A
Execute Test A
Delete HTML file

这样,当您在路上添加测试ZZZZZ时,您将拥有提供测试数据的一致方法。

如果您只是运行有限数量的测试,并且它将保持这种状态,那么一些预先编写的静态HTML文件应该没问题。

当然,正如Rich建议的那样做一些集成测试。

答案 7 :(得分:1)

你正在创建一个外部依赖,这将是脆弱的。

为什么不创建一个TestContent项目,填充一堆资源文件?复制'n将您的源HTML粘贴到资源文件中,然后您可以在单元测试中引用它们。

答案 8 :(得分:1)

听起来你在这里有几个组件:

  • 获取HTML内容的内容
  • 剥去箔条的东西,只产生必须刮掉的文字
  • 实际查看内容并将其转换为数据库/无论
  • 的内容

您应该独立测试(并且可能)实施刮刀的这些部分。

没有理由你不能从任何地方获取内容(即没有HTTP)。

除了刮擦之外,没有理由你不想剥离箔条。

没有理由只通过抓取将数据存储到您的数据库中。

所以..没有理由将所有这些代码构建和测试为一个大型程序。

然后......也许我们过度复杂了?

答案 9 :(得分:0)

我不明白为什么在你的单元测试中html起源于何处。 澄清一下:您的单元测试正在处理html内容,其中内容来源并不重要,因此从文件中读取它对于您的单元测试来说很好。正如你在评论中所说的那样,你肯定不想为每次测试都打网络,因为这只是开销。

您也可能想要添加一两个集成测试,以检查您是否正确处理了网址(即您可以连接和处理外部网址)。

答案 10 :(得分:0)

除了一两个测试之外,您应该查询磁盘上的静态页面。但是不要忘记那些触摸网络的测试!