测试Gradle脚本的最佳做法是什么?
我目前使用ant对我的antunit脚本进行单元测试,但我希望迁移到Gradle。我只能找到有关从Gradle或Groovy测试Java代码的文章,但没有关于测试我创建或一般测试Groovy的Gradle任务的内容。是否有相当于Gradle的蚂蚁?有没有人使用BDD框架(如cucumber)来测试Gradle脚本?
例如,我目前有以下Ant目标
<target name="dist-bin" depends="build" description="creates a zip distribution of the current build">
<zip destfile="build/TIBant-bin.zip">
<zipfileset dir="src/ant" includes="**" />
<zipfileset dir="test" includes="**" prefix="test" />
<zipfileset dir="build" includes="TIBant.jar" />
<zipfileset dir="build" includes="TIBant-*.html" />
<zipfileset dir="build/examples/XMLtoProperties"
includes="XMLtoProperties.html"
prefix="examples/XMLtoProperties" />
<zipfileset dir="lib" includes="**" prefix="lib" />
<zipfileset dir="src/xslt" includes="**" excludes="test/**,userguide.xslt" prefix="lib/xslt" />
<zipfileset dir="." includes="copyright.html,LICENSE.txt" />
<zipfileset dir="examples"
includes="**"
excludes="**/build/**,**/config/default.properties"
prefix="examples" />
</zip>
</target>
你可以想象,在重构项目时很容易打破这个,所以我有以下的antunit测试来检查它。
<target name="test-dist-bin">
<delete file="build/TIBant-bin.zip" />
<au:assertFalse message="Bin dist still present">
<available file="build/TIBant-bin.zip" />
</au:assertFalse>
<antcall target="dist-bin" />
<au:assertTrue message="Bin dist not created">
<available file="build/TIBant-bin.zip" />
</au:assertTrue>
<delete dir="build/testBinDist" />
<au:assertFalse message="TestBinDist still present">
<available file="build/testBinDist" />
</au:assertFalse>
<mkdir dir="build/testBinDist" />
<unzip src="build/TIBant-bin.zip" dest="build/testBinDist" />
<au:assertFalse message="config dir present">
<available file="build/testBinDist/config/default.properties" />
</au:assertFalse>
<au:assertTrue message="Ant Macros missing">
<available file="build/testBinDist/tibant.xml" />
</au:assertTrue>
<au:assertTrue message="Engine Stopper Jar missing">
<available file="build/testBinDist/TIBant.jar" />
</au:assertTrue>
<au:assertTrue message="Ant-contrib-missing">
<available file="build/testBinDist/lib/ant-contrib-1.0b3.jar" />
</au:assertTrue>
<au:assertTrue message="ant-unit missing">
<available file="build/testBinDist/lib/ant-antunit-1.2.jar" />
</au:assertTrue>
<au:assertTrue message="Copyright missing">
<available file="build/testBinDist/copyright.html" />
</au:assertTrue>
<au:assertTrue message="License missing">
<available file="build/testBinDist/LICENSE.txt" />
</au:assertTrue>
<au:assertFalse message="Src present">
<available file="build/testBinDist/src/java/org/windyroad/tibant/EngineStopper.jar" />
</au:assertFalse>
<au:assertTrue message="example missing">
<available file="build/testBinDist/examples/SimpleProject/src/bw/example/Build/example.archive" />
</au:assertTrue>
<au:assertFalse message="example has build files">
<available file="build/testBinDist/examples/SimpleProject/build/*" />
</au:assertFalse>
<au:assertFalse message="example has default config file">
<available file="build/testBinDist/examples/SimpleProject/config/default.properties" />
</au:assertFalse>
<property name="doc.file"
location="build/testBinDist/TIBant-User-Guide.html" />
<au:assertTrue message="doc missing: ${doc.file}">
<available file="${doc.file}" />
</au:assertTrue>
<au:assertTrue message="xslt missing">
<available file="build/testBinDist/lib/xslt/configure-ear.xslt" />
</au:assertTrue>
<subant target="run-quick-tests">
<fileset dir="build/testBinDist" includes="build.xml" />
</subant>
</target>
由以下代码段调用,以生成一个不错的xml报告
<au:antunit failonerror="@{failonerror}">
<propertyset>
<propertyref name="config.filename" />
</propertyset>
<path>
<pathelement location="@{antunit}" />
</path>
<au:plainlistener logLevel="info" />
<au:xmllistener todir="build" loglevel="info" />
</au:antunit>
我了解如何将dist-bin
迁移到gradle,但我不确定迁移test-dist-bin
和au:antunit
电话的正确方法是什么。
答案 0 :(得分:5)
我认为汤姆的意思是测试他自己的书面格斗任务的方法,对吧?如果您通过扩展DefaultTask编写了自定义gradle任务并将其放在项目的buildSrc文件夹中,则可以添加junit / spock /无论基于什么的测试类来测试您的任务实现。 Gradles自己的构建为此提供了一个很好的例子。看看
这是一个spock规范,它测试ExtractDslMetaDataTask,它是专门为griddles自己构建的。 ExtractDslMetaDataTask位于:
要将断言添加到构建脚本“adhoc tasks”,就像上面的例子一样,你可以使用groovy power断言。
一个例子: 如果你在脚本中有一个非常简单的任务:
task writeFoo << {
file("$buildDir/foo.txt").text = "bar"
}
您可以修改任务本身以添加断言:
task writeFoo << {
file("$buildDir/foo.txt").text = "bar"
assert file("$buildDir/foo.txt).isFile()
}
或者在脚本中添加专用测试任务
task testWriteFoo(dependsOn: writeFoo) << {
assert file("$buildDir/foo.txt).isFile()
assert file("$buildDir/foo.txt).text == "bar"
}
请记住,您可以在构建脚本中使用groovy语言的全部功能。
计划在gradle中集成一个测试工具包,以支持构建脚本作者测试他们的自定义构建逻辑。看看:
http://forums.gradle.org/gradle/topics/testing_toolkit_for_custom_build_logic
答案 1 :(得分:3)
只要您应用插件groovy
并且您的测试位于src/test/groovy
下,就无需运行它们。例如,对于使用Spock的BDD测试也是如此。如果您想了解有关Gradle测试功能的更多信息,请查看书籍Building and Testing with Gradle。它涵盖了使用JUnit,TestNG,Spock,Geb和EasyB进行测试。
答案 2 :(得分:2)
Gradle 3.x测试工具包可用! 请在此处查看用户指南:https://docs.gradle.org/current/userguide/test_kit.html
然后可以通过断言以下内容来验证逻辑的正确性,可能是组合:
复制粘贴示例:
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.GradleRunner;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.gradle.testkit.runner.TaskOutcome.*;
public class BuildLogicFunctionalTest {
@Rule public final TemporaryFolder testProjectDir = new TemporaryFolder();
private File buildFile;
@Before
public void setup() throws IOException {
buildFile = testProjectDir.newFile("build.gradle");
}
@Test
public void testHelloWorldTask() throws IOException {
String buildFileContent = "task helloWorld {" +
" doLast {" +
" println 'Hello world!'" +
" }" +
"}";
writeFile(buildFile, buildFileContent);
BuildResult result = GradleRunner.create()
.withProjectDir(testProjectDir.getRoot())
.withArguments("helloWorld")
.build();
assertTrue(result.getOutput().contains("Hello world!"));
assertEquals(result.task(":helloWorld").getOutcome(), SUCCESS);
}
private void writeFile(File destination, String content) throws IOException {
BufferedWriter output = null;
try {
output = new BufferedWriter(new FileWriter(destination));
output.write(content);
} finally {
if (output != null) {
output.close();
}
}
}
}