自动样品测试的Exemplar系统基本介绍和使用教程

251 阅读3分钟

这篇文章介绍了一个叫做Exemplar的新库。 Exemplar的目标是确保用户得到你期望他们看到的输出。 它处理样本发现、规范化(语义上等同的结果,也许来自不同的环境),以及灵活的输出验证。 它在要调用的环境中调用任何命令行工具。你也可以调用curl ,例如,验证服务API响应。

Gradle使用这个库来验证文档和指南中的例子,并从集成测试中删除模板。

Exemplar可以使用JUnit测试运行器(推荐)或使用其API进行配置。 见下面的例子和Exemplar GitHub repo中的例子: image.png

Exemplar的使用情况

文档样本的准确性是很重要的。 想象一下,当你想学习新的东西时,却发现例子无法使用,这是很令人沮丧的。

我们认为Exemplar作为一种文档检查机制效果最好,但它并不是要取代其他形式的集成测试。

Exemplar是独特的,因为它允许发现嵌入在结构化文档中的样本,以及OutputNormalizers (捆绑的和自定义的),方便在 "更传统的 "集成测试中使用样本项目(通过@UsesSample("path/to/sample") ),并允许样本在执行前被编程修改(也许是为了额外的环境设置)(SampleModifier )。

Exemplar专注于日志和退出代码的输出,验证其他副作用是很麻烦的(检查创建的文件可能需要额外的命令)。 此外,尽管Exemplar可以用于任何工具,但它只有JVM项目的API。

示例项目测试入门

Exemplar中的sample-discovery 库会将样本根目录下任何包含*.sample.conf 文件的目录视为一个样本项目。

一个样本配置文件是用HOCON写的,它告诉sample-check 如何运行这个样本项目。这非常简单:

executable: echo
args: "Hello World"

也可以很复杂,有多个步骤:

commands: [{
  executable: gradle
  args: originalInputs incrementalReverse
  expected-output-file: originalInputs.out
  allow-additional-output: true
}, {
  executable: gradle
  args: --quiet removeOutput incrementalReverse
  expected-output-file: incrementalTaskRemovedOutput.out
  allow-disordered-output: true
}]

参见文档中的样本配置参考,以了解有哪些选项可用。

然后,一个JUnit测试声明了哪些@SampleRunner ,以及样本测试的其他方面。

@RunWith(GradleSamplesRunner.class)
@SamplesRoot("src/docs/samples")
@SamplesOutputNormalizers({JavaObjectSerializationOutputNormalizer.class, FileSeparatorOutputNormalizer.class})
public class SamplesIntegrationTest {}

执行这个测试将发现并运行外部(即非嵌入式)样本项目,并像你所期望的那样生成JUnit测试报告。

嵌入式样本测试入门

Exemplar可以使用Asciidoctor的AST发现Asciidoctor源文件内的样本。 这里有一个例子,也是使用SampleModifiers ,也是设置Samples的环境。

.Sample title
====
[.testable-sample]       (1)
=====
.hello.rb                (2)
[source,ruby]            (3)
-----
puts "hello, #{ARGV[0]}" (4)
-----

[.sample-command]        (5)
-----
$ ruby hello.rb world    (6)
hello, world             (7)
-----
=====
====

请阅读嵌入式样本的文档,以了解允许这样做的Asciidoctor元素。

我们使用指向docs/ 根目录的EmbeddedSamplesRunner 来运行这个测试,Exemplar将在该目录下寻找文档文件:

@RunWith(EmbeddedSamplesRunner.class)
@SamplesRoot("docs")
@SampleModifiers({SetupEnvironmentSampleModifier.class, ExtraCommandArgumentsSampleModifier.class})
public class EmbeddedSamplesIntegrationTest {}

执行这个测试将从Asciidoctor提取代码到一个临时项目中,运行它,并验证它与文档中声明的输出相匹配。

采用和贡献

开始的最好方法是阅读Exemplar文档,并查看Exemplar的样本测试样本

在写这篇文章的时候,Exemplar的版本是0.6,这意味着API在v1.0之前可能会有变化。尽管如此,考虑到API已经经历了一些修订,并且已经被Gradle采用,在1.0版本之前不太可能有突破性的变化。

以下是一些可能是该库的良好扩展的东西,如果你渴望提出想法或向gradle/exemplar GitHub repo提交拉动请求,我很愿意得到你的帮助:

  • 更多的标准规范化器,如日期、时间或持续时间的规范化
  • 为搜索索引生成结构化的元数据
  • 允许在样本配置文件中内联预期输出
  • 在Markdown或其他文档格式中嵌入样本发现(#2938)。

如果你想在这个项目中得到指导,请联系我(Twitter上的@eriwen)。