Browse Source
- Look for JUnit test symbols, and add JUnit automatically - Look for Spock test symbols, and add Spock automatically - Based on what test libraries were used, invoke relevant embedded testers and accumulate results - Make it so that multiple testers can be invoked through a single 'test' command - Print out total results and write out detailed trace errors in results.txt - Update based on the new artifact resolution mechanismpull/69/head
26 changed files with 990 additions and 12 deletions
@ -0,0 +1,264 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli.command; |
||||||
|
|
||||||
|
import groovy.lang.GroovyObject; |
||||||
|
import joptsimple.OptionSet; |
||||||
|
import org.apache.ivy.util.FileUtil; |
||||||
|
import org.springframework.boot.cli.Log; |
||||||
|
import org.springframework.boot.cli.command.tester.Failure; |
||||||
|
import org.springframework.boot.cli.command.tester.TestResults; |
||||||
|
import org.springframework.boot.cli.compiler.GroovyCompiler; |
||||||
|
import org.springframework.boot.cli.compiler.GroovyCompilerConfiguration; |
||||||
|
|
||||||
|
import java.io.File; |
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.PrintWriter; |
||||||
|
import java.net.URL; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.HashSet; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Scanner; |
||||||
|
import java.util.Set; |
||||||
|
import java.util.logging.Level; |
||||||
|
|
||||||
|
/** |
||||||
|
* Invokes testing for autocompiled scripts |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
public class TestCommand extends OptionParsingCommand { |
||||||
|
|
||||||
|
private TestOptionHandler testOptionHandler; |
||||||
|
|
||||||
|
public TestCommand() { |
||||||
|
super("test", "Test a groovy script", new TestOptionHandler()); |
||||||
|
this.testOptionHandler = (TestOptionHandler)this.getHandler(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getUsageHelp() { |
||||||
|
return "[options] <files>"; |
||||||
|
} |
||||||
|
|
||||||
|
public TestResults getResults() { |
||||||
|
return testOptionHandler.results; |
||||||
|
} |
||||||
|
|
||||||
|
private static class TestGroovyCompilerConfiguration implements GroovyCompilerConfiguration { |
||||||
|
@Override |
||||||
|
public boolean isGuessImports() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isGuessDependencies() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getClasspath() { |
||||||
|
return ""; |
||||||
|
} |
||||||
|
|
||||||
|
public Level getLogLevel() { |
||||||
|
return Level.INFO; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static class TestOptionHandler extends OptionHandler { |
||||||
|
|
||||||
|
private final GroovyCompiler compiler; |
||||||
|
|
||||||
|
private TestResults results; |
||||||
|
|
||||||
|
public TestOptionHandler() { |
||||||
|
TestGroovyCompilerConfiguration configuration = new TestGroovyCompilerConfiguration(); |
||||||
|
this.compiler = new GroovyCompiler(configuration); |
||||||
|
if (configuration.getLogLevel().intValue() <= Level.FINE.intValue()) { |
||||||
|
System.setProperty("groovy.grape.report.downloads", "true"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void run(OptionSet options) throws Exception { |
||||||
|
List<?> nonOptionArguments = options.nonOptionArguments(); |
||||||
|
|
||||||
|
Set<File> testerFiles = new HashSet<File>(); |
||||||
|
File[] files = getFileArguments(nonOptionArguments, testerFiles); |
||||||
|
|
||||||
|
/* |
||||||
|
* Need to compile the code twice: The first time automatically |
||||||
|
* pulls in autoconfigured libraries including test tools. Then |
||||||
|
* the compiled code can be scanned to see what libraries were |
||||||
|
* activated. Then it can be recompiled, with appropriate tester |
||||||
|
* groovy scripts included in the same classloading context. Then |
||||||
|
* the testers can be fetched and invoked through reflection against |
||||||
|
* the composite AST. |
||||||
|
*/ |
||||||
|
// Compile - Pass 1
|
||||||
|
Object[] sources = this.compiler.sources(files); |
||||||
|
|
||||||
|
boolean testing = false; |
||||||
|
try { |
||||||
|
check("org.junit.Test", sources); |
||||||
|
testerFiles.add(locateSourceFromUrl("junit", "testers/junit.groovy")); |
||||||
|
testing = true; |
||||||
|
} catch (ClassNotFoundException e) { |
||||||
|
} |
||||||
|
|
||||||
|
try { |
||||||
|
check("spock.lang.Specification", sources); |
||||||
|
testerFiles.add(locateSourceFromUrl("spock", "testers/spock.groovy")); |
||||||
|
testing = true; |
||||||
|
} catch (ClassNotFoundException e) { |
||||||
|
} |
||||||
|
|
||||||
|
if (testing) { |
||||||
|
testerFiles.add(locateSourceFromUrl("tester", "testers/tester.groovy")); |
||||||
|
} |
||||||
|
|
||||||
|
// Compile - Pass 2 - with appropriate testers added in
|
||||||
|
files = getFileArguments(nonOptionArguments, testerFiles); |
||||||
|
sources = this.compiler.sources(files); |
||||||
|
|
||||||
|
|
||||||
|
if (sources.length == 0) { |
||||||
|
throw new RuntimeException("No classes found in '" + files + "'"); |
||||||
|
} |
||||||
|
|
||||||
|
List<Class<?>> testers = new ArrayList<Class<?>>(); |
||||||
|
|
||||||
|
// Extract list of compiled classes
|
||||||
|
List<Class<?>> compiled = new ArrayList<Class<?>>(); |
||||||
|
for (Object source : sources) { |
||||||
|
if (source.getClass() == Class.class) { |
||||||
|
Class<?> sourceClass = (Class<?>)source; |
||||||
|
if (sourceClass.getSuperclass().getName().equals("AbstractTester")) { |
||||||
|
testers.add(sourceClass); |
||||||
|
} else { |
||||||
|
compiled.add((Class<?>)source); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
this.results = new TestResults(); |
||||||
|
|
||||||
|
for (Class<?> tester : testers) { |
||||||
|
GroovyObject obj = (GroovyObject)tester.newInstance(); |
||||||
|
this.results.add((TestResults)obj.invokeMethod("findAndTest", compiled)); |
||||||
|
} |
||||||
|
|
||||||
|
printReport(this.results); |
||||||
|
} |
||||||
|
|
||||||
|
private File locateSourceFromUrl(String name, String path) { |
||||||
|
try { |
||||||
|
File file = File.createTempFile(name, ".groovy"); |
||||||
|
file.deleteOnExit(); |
||||||
|
FileUtil.copy(getClass().getClassLoader().getResourceAsStream(path), file, null); |
||||||
|
return file; |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
throw new IllegalStateException("Could not create temp file for source: " |
||||||
|
+ name); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private Class<?> check(String className, Object[] sources) throws ClassNotFoundException { |
||||||
|
Class<?> classToReturn = null; |
||||||
|
ClassNotFoundException classNotFoundException = null; |
||||||
|
for (Object source : sources) { |
||||||
|
try { |
||||||
|
classToReturn = ((Class<?>)source).getClassLoader().loadClass(className); |
||||||
|
} catch (ClassNotFoundException e) { |
||||||
|
classNotFoundException = e; |
||||||
|
} |
||||||
|
} |
||||||
|
if (classToReturn != null) { |
||||||
|
return classToReturn; |
||||||
|
} |
||||||
|
throw classNotFoundException; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private File[] getFileArguments(List<?> nonOptionArguments, Set<File> testerFiles) { |
||||||
|
List<File> files = new ArrayList<File>(); |
||||||
|
for (Object option : nonOptionArguments) { |
||||||
|
if (option instanceof String) { |
||||||
|
String filename = (String) option; |
||||||
|
if ("--".equals(filename)) { |
||||||
|
break; |
||||||
|
} |
||||||
|
if (filename.endsWith(".groovy") || filename.endsWith(".java")) { |
||||||
|
File file = new File(filename); |
||||||
|
if (file.isFile() && file.canRead()) { |
||||||
|
files.add(file); |
||||||
|
} |
||||||
|
else { |
||||||
|
URL url = getClass().getClassLoader().getResource(filename); |
||||||
|
if (url != null) { |
||||||
|
if (url.toString().startsWith("file:")) { |
||||||
|
files.add(new File(url.toString().substring("file:".length()))); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new RuntimeException("Can't find " + filename); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (files.size() == 0) { |
||||||
|
throw new RuntimeException("Please specify a file to run"); |
||||||
|
} |
||||||
|
|
||||||
|
for (File testerFile : testerFiles) { |
||||||
|
files.add(testerFile); |
||||||
|
} |
||||||
|
|
||||||
|
return files.toArray(new File[files.size()]); |
||||||
|
} |
||||||
|
|
||||||
|
private void printReport(TestResults results) throws FileNotFoundException { |
||||||
|
PrintWriter writer = new PrintWriter("results.txt"); |
||||||
|
|
||||||
|
String header = "Total: " + results.getRunCount() + |
||||||
|
", Success: " + (results.getRunCount()-results.getFailureCount()) + |
||||||
|
", : Failures: " + results.getFailureCount() + "\n" + |
||||||
|
"Passed? " + results.wasSuccessful(); |
||||||
|
|
||||||
|
String trailer = ""; |
||||||
|
String trace = ""; |
||||||
|
for (Failure failure : results.getFailures()) { |
||||||
|
trailer += failure.getDescription().toString(); |
||||||
|
trace += failure.getTrace() + "\n"; |
||||||
|
} |
||||||
|
|
||||||
|
writer.println(header); |
||||||
|
writer.println(trace); |
||||||
|
writer.close(); |
||||||
|
|
||||||
|
Log.info(header); |
||||||
|
Log.info(trailer); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli.command.tester; |
||||||
|
|
||||||
|
import java.io.FileNotFoundException; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Set; |
||||||
|
|
||||||
|
public abstract class AbstractTester { |
||||||
|
|
||||||
|
public TestResults findAndTest(List<Class<?>> compiled) throws FileNotFoundException { |
||||||
|
Set<Class<?>> testable = findTestableClasses(compiled); |
||||||
|
|
||||||
|
if (testable.size() == 0) { |
||||||
|
return TestResults.none; |
||||||
|
} |
||||||
|
|
||||||
|
return test(testable.toArray(new Class<?>[]{})); |
||||||
|
} |
||||||
|
|
||||||
|
abstract protected Set<Class<?>> findTestableClasses(List<Class<?>> compiled); |
||||||
|
|
||||||
|
abstract protected TestResults test(Class<?>[] testable); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli.command.tester; |
||||||
|
|
||||||
|
/** |
||||||
|
* Platform neutral way to capture a test failure |
||||||
|
* |
||||||
|
* NOTE: This is needed to avoid having to add JUnit jar file to the deployable artifacts |
||||||
|
*/ |
||||||
|
public class Failure { |
||||||
|
private String description; |
||||||
|
private String trace; |
||||||
|
|
||||||
|
public Failure(String description, String trace) { |
||||||
|
this.description = description; |
||||||
|
this.trace = trace; |
||||||
|
} |
||||||
|
|
||||||
|
public String getDescription() { |
||||||
|
return description; |
||||||
|
} |
||||||
|
|
||||||
|
public void setDescription(String description) { |
||||||
|
this.description = description; |
||||||
|
} |
||||||
|
|
||||||
|
public String getTrace() { |
||||||
|
return trace; |
||||||
|
} |
||||||
|
|
||||||
|
public void setTrace(String trace) { |
||||||
|
this.trace = trace; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,94 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli.command.tester; |
||||||
|
|
||||||
|
import java.util.Arrays; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* Platform neutral way to collect test results |
||||||
|
* |
||||||
|
* NOTE: This is needed to avoid having to add JUnit's jar file to the deployable artifacts |
||||||
|
*/ |
||||||
|
public class TestResults { |
||||||
|
|
||||||
|
public static final NoTestResults none = new NoTestResults(); |
||||||
|
|
||||||
|
private int runCount; |
||||||
|
private int failureCount; |
||||||
|
private Failure[] failures = new Failure[0]; |
||||||
|
|
||||||
|
public void add(TestResults results) { |
||||||
|
this.runCount += results.getRunCount(); |
||||||
|
this.failureCount += results.getFailureCount(); |
||||||
|
|
||||||
|
List<Failure> failures = Arrays.asList(this.failures); |
||||||
|
failures.addAll(Arrays.asList(results.getFailures())); |
||||||
|
this.failures = failures.toArray(new Failure[]{}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public boolean wasSuccessful() { |
||||||
|
return this.failureCount == 0; |
||||||
|
} |
||||||
|
|
||||||
|
public int getRunCount() { |
||||||
|
return runCount; |
||||||
|
} |
||||||
|
|
||||||
|
public void setRunCount(int runCount) { |
||||||
|
this.runCount = runCount; |
||||||
|
} |
||||||
|
|
||||||
|
public int getFailureCount() { |
||||||
|
return failureCount; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFailureCount(int failureCount) { |
||||||
|
this.failureCount = failureCount; |
||||||
|
} |
||||||
|
|
||||||
|
public Failure[] getFailures() { |
||||||
|
return failures; |
||||||
|
} |
||||||
|
|
||||||
|
public void setFailures(Failure[] failures) { |
||||||
|
this.failures = failures; |
||||||
|
} |
||||||
|
|
||||||
|
private static class NoTestResults extends TestResults { |
||||||
|
@Override |
||||||
|
public int getRunCount() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int getFailureCount() { |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Failure[] getFailures() { |
||||||
|
return new Failure[0]; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean wasSuccessful() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,52 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli.compiler.autoconfigure; |
||||||
|
|
||||||
|
import org.codehaus.groovy.ast.ClassNode; |
||||||
|
import org.codehaus.groovy.control.CompilationFailedException; |
||||||
|
import org.codehaus.groovy.control.customizers.ImportCustomizer; |
||||||
|
import org.springframework.boot.cli.compiler.AstUtils; |
||||||
|
import org.springframework.boot.cli.compiler.CompilerAutoConfiguration; |
||||||
|
import org.springframework.boot.cli.compiler.DependencyCustomizer; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link CompilerAutoConfiguration} for JUnit |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
public class JUnitCompilerAutoConfiguration extends CompilerAutoConfiguration { |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean matches(ClassNode classNode) { |
||||||
|
return AstUtils.hasAtLeastOneAnnotation(classNode, "Test"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void applyDependencies(DependencyCustomizer dependencies) |
||||||
|
throws CompilationFailedException { |
||||||
|
dependencies.add("junit").add("spring-test").add("hamcrest-library"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void applyImports(ImportCustomizer imports) throws CompilationFailedException { |
||||||
|
imports.addStarImports("org.junit") |
||||||
|
.addStaticStars("org.junit.Assert").addImports() |
||||||
|
.addStaticStars("org.hamcrest.MatcherAssert") |
||||||
|
.addStaticStars("org.hamcrest.Matchers"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli.compiler.autoconfigure; |
||||||
|
|
||||||
|
import org.codehaus.groovy.ast.ClassNode; |
||||||
|
import org.codehaus.groovy.control.CompilationFailedException; |
||||||
|
import org.codehaus.groovy.control.customizers.ImportCustomizer; |
||||||
|
import org.springframework.boot.cli.compiler.AstUtils; |
||||||
|
import org.springframework.boot.cli.compiler.CompilerAutoConfiguration; |
||||||
|
import org.springframework.boot.cli.compiler.DependencyCustomizer; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link CompilerAutoConfiguration} for Spock test framework |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
public class SpockCompilerAutoConfiguration extends CompilerAutoConfiguration { |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean matches(ClassNode classNode) { |
||||||
|
return AstUtils.subclasses(classNode, "Specification"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void applyDependencies(DependencyCustomizer dependencies) |
||||||
|
throws CompilationFailedException { |
||||||
|
dependencies.add("spock-core"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void applyImports(ImportCustomizer imports) throws CompilationFailedException { |
||||||
|
imports.addStarImports("spock.lang"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,14 @@ |
|||||||
|
groovy.version: ${groovy.version} |
||||||
|
hamcrest.version: ${hamcrest.version} |
||||||
|
jetty.version: ${jetty.version} |
||||||
|
junit.version: ${junit.version} |
||||||
|
reactor.version: ${reactor.version} |
||||||
|
spock.version: ${spock.version} |
||||||
|
spring.version: ${spring.version} |
||||||
|
spring-batch.version: ${spring-batch.version} |
||||||
|
spring-boot.version: ${project.version} |
||||||
|
spring-rabbit.version: ${spring-rabbit.version} |
||||||
|
spring-security.version: ${spring-security.version} |
||||||
|
spring-integration.version: ${spring-integration.version} |
||||||
|
spring-integration-groovydsl.version: ${spring-integration-groovydsl.version} |
||||||
|
tomcat.version: ${tomcat.version} |
||||||
@ -0,0 +1,125 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
package org.springframework.boot.cli; |
||||||
|
|
||||||
|
import org.junit.After; |
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.BeforeClass; |
||||||
|
import org.junit.Test; |
||||||
|
import org.springframework.boot.cli.command.CleanCommand; |
||||||
|
import org.springframework.boot.cli.command.TestCommand; |
||||||
|
import org.springframework.boot.cli.command.tester.TestResults; |
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals; |
||||||
|
import static org.junit.Assert.assertTrue; |
||||||
|
|
||||||
|
/** |
||||||
|
* Integration tests to exercise the CLI's test command. |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
public class TestCommandIntegrationTests { |
||||||
|
|
||||||
|
@BeforeClass |
||||||
|
public static void cleanGrapes() throws Exception { |
||||||
|
GrapesCleaner.cleanIfNecessary(); |
||||||
|
// System.setProperty("ivy.message.logger.level", "3");
|
||||||
|
} |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setup() throws Exception { |
||||||
|
System.setProperty("disableSpringSnapshotRepos", "true"); |
||||||
|
new CleanCommand().run("org.springframework"); |
||||||
|
} |
||||||
|
|
||||||
|
@After |
||||||
|
public void teardown() { |
||||||
|
System.clearProperty("disableSpringSnapshotRepos"); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void noTests() throws Throwable { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/book.groovy"); |
||||||
|
TestResults results = command.getResults(); |
||||||
|
assertEquals(0, results.getRunCount()); |
||||||
|
assertEquals(0, results.getFailureCount()); |
||||||
|
assertTrue(results.wasSuccessful()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void empty() throws Exception { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/empty.groovy"); |
||||||
|
TestResults results = command.getResults(); |
||||||
|
assertEquals(0, results.getRunCount()); |
||||||
|
assertEquals(0, results.getFailureCount()); |
||||||
|
assertTrue(results.wasSuccessful()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test(expected = RuntimeException.class) |
||||||
|
public void noFile() throws Exception { |
||||||
|
try { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/nothing.groovy"); |
||||||
|
} catch (RuntimeException e) { |
||||||
|
assertEquals("Can't find testscripts/nothing.groovy", e.getMessage()); |
||||||
|
throw e; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void appAndTestsInOneFile() throws Exception { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/book_and_tests.groovy"); |
||||||
|
TestResults results = command.getResults(); |
||||||
|
assertEquals(1, results.getRunCount()); |
||||||
|
assertEquals(0, results.getFailureCount()); |
||||||
|
assertTrue(results.wasSuccessful()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void appInOneFileTestsInAnotherFile() throws Exception { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/book.groovy", "testscripts/test.groovy"); |
||||||
|
TestResults results = command.getResults(); |
||||||
|
assertEquals(1, results.getRunCount()); |
||||||
|
assertEquals(0, results.getFailureCount()); |
||||||
|
assertTrue(results.wasSuccessful()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void spockTester() throws Exception { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/spock.groovy"); |
||||||
|
TestResults results = command.getResults(); |
||||||
|
assertEquals(1, results.getRunCount()); |
||||||
|
assertEquals(0, results.getFailureCount()); |
||||||
|
assertTrue(results.wasSuccessful()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void spockAndJunitTester() throws Exception { |
||||||
|
TestCommand command = new TestCommand(); |
||||||
|
command.run("testscripts/spock.groovy", "testscripts/book_and_tests.groovy"); |
||||||
|
TestResults results = command.getResults(); |
||||||
|
assertEquals(2, results.getRunCount()); |
||||||
|
assertEquals(0, results.getFailureCount()); |
||||||
|
assertTrue(results.wasSuccessful()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,68 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License") |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import org.junit.runner.JUnitCore |
||||||
|
import org.junit.runner.Result |
||||||
|
import org.springframework.boot.cli.command.tester.Failure |
||||||
|
import org.springframework.boot.cli.command.tester.TestResults |
||||||
|
|
||||||
|
import java.lang.annotation.Annotation |
||||||
|
import java.lang.reflect.Method |
||||||
|
|
||||||
|
/** |
||||||
|
* Groovy script to run JUnit tests inside the {@link TestCommand}. |
||||||
|
* Needs to be compiled along with the actual code to work properly. |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
class JUnitTester extends AbstractTester { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Set<Class<?>> findTestableClasses(List<Class<?>> compiled) { |
||||||
|
// Look for @Test methods |
||||||
|
Set<Class<?>> testable = new LinkedHashSet<Class<?>>() |
||||||
|
for (Class<?> clazz : compiled) { |
||||||
|
for (Method method : clazz.getMethods()) { |
||||||
|
for (Annotation annotation : method.getAnnotations()) { |
||||||
|
if (annotation.toString().contains("Test")) { |
||||||
|
testable.add(clazz) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return testable |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected TestResults test(Class<?>[] testable) { |
||||||
|
Result results = JUnitCore.runClasses(testable) |
||||||
|
|
||||||
|
TestResults testResults = new TestResults() |
||||||
|
testResults.setFailureCount(results.getFailureCount()) |
||||||
|
testResults.setRunCount(results.getRunCount()) |
||||||
|
|
||||||
|
List<org.springframework.boot.cli.command.tester.Failure> failures = |
||||||
|
new ArrayList<Failure>() |
||||||
|
for (org.junit.runner.notification.Failure failure : results.getFailures()) { |
||||||
|
failures.add(new Failure(failure.getDescription().toString(), failure.getTrace())) |
||||||
|
} |
||||||
|
|
||||||
|
testResults.setFailures(failures.toArray(new Failure[0])) |
||||||
|
|
||||||
|
return testResults |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,62 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License") |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import org.junit.runner.Result |
||||||
|
import org.springframework.boot.cli.command.tester.Failure |
||||||
|
import org.springframework.boot.cli.command.tester.TestResults |
||||||
|
import spock.lang.Specification |
||||||
|
import spock.util.EmbeddedSpecRunner |
||||||
|
|
||||||
|
/** |
||||||
|
* Groovy script to run Spock tests inside the {@link TestCommand}. |
||||||
|
* Needs to be compiled along with the actual code to work properly. |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
class SpockTester extends AbstractTester { |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Set<Class<?>> findTestableClasses(List<Class<?>> compiled) { |
||||||
|
// Look for classes that implement spock.lang.Specification |
||||||
|
Set<Class<?>> testable = new LinkedHashSet<Class<?>>() |
||||||
|
for (Class<?> clazz : compiled) { |
||||||
|
if (Specification.class.isAssignableFrom(clazz)) { |
||||||
|
testable.add(clazz) |
||||||
|
} |
||||||
|
} |
||||||
|
return testable |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected TestResults test(Class<?>[] testable) { |
||||||
|
Result results = new EmbeddedSpecRunner().runClasses(Arrays.asList(testable)) |
||||||
|
|
||||||
|
TestResults testResults = new TestResults() |
||||||
|
testResults.setFailureCount(results.getFailureCount()) |
||||||
|
testResults.setRunCount(results.getRunCount()) |
||||||
|
|
||||||
|
List<org.springframework.boot.cli.command.tester.Failure> failures = |
||||||
|
new ArrayList<Failure>() |
||||||
|
for (org.junit.runner.notification.Failure failure : results.getFailures()) { |
||||||
|
failures.add(new Failure(failure.getDescription().toString(), failure.getTrace())) |
||||||
|
} |
||||||
|
|
||||||
|
testResults.setFailures(failures.toArray(new Failure[0])) |
||||||
|
|
||||||
|
return testResults |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2012-2013 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License") |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
|
||||||
|
import org.springframework.boot.cli.command.tester.TestResults |
||||||
|
|
||||||
|
/** |
||||||
|
* Groovy script define abstract basis for automated testers for {@link TestCommand}. |
||||||
|
* Needs to be compiled along with the actual code to work properly. |
||||||
|
* |
||||||
|
* @author Greg Turnquist |
||||||
|
*/ |
||||||
|
public abstract class AbstractTester { |
||||||
|
|
||||||
|
public TestResults findAndTest(List<Class<?>> compiled) throws FileNotFoundException { |
||||||
|
Set<Class<?>> testable = findTestableClasses(compiled) |
||||||
|
|
||||||
|
if (testable.size() == 0) { |
||||||
|
return TestResults.none |
||||||
|
} |
||||||
|
|
||||||
|
return test(testable.toArray(new Class<?>[0])) |
||||||
|
} |
||||||
|
|
||||||
|
abstract protected Set<Class<?>> findTestableClasses(List<Class<?>> compiled) |
||||||
|
|
||||||
|
abstract protected TestResults test(Class<?>[] testable) |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
class Book { |
||||||
|
String author |
||||||
|
String title |
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
class Book { |
||||||
|
String author |
||||||
|
String title |
||||||
|
} |
||||||
|
|
||||||
|
class BookTests { |
||||||
|
@Test |
||||||
|
void testBooks() { |
||||||
|
Book book = new Book(author: "Tom Clancy", title: "Threat Vector") |
||||||
|
assertEquals("Tom Clancy", book.author) |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,12 @@ |
|||||||
|
class HelloSpock extends Specification { |
||||||
|
def "length of Spock's and his friends' names"() { |
||||||
|
expect: |
||||||
|
name.size() == length |
||||||
|
|
||||||
|
where: |
||||||
|
name | length |
||||||
|
"Spock" | 5 |
||||||
|
"Kirk" | 4 |
||||||
|
"Scotty" | 6 |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,7 @@ |
|||||||
|
class BookTests { |
||||||
|
@Test |
||||||
|
void testBooks() { |
||||||
|
Book book = new Book(author: "Tom Clancy", title: "Threat Vector") |
||||||
|
assertEquals("Tom Clancy", book.author) |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue