Skip to content

Commit

Permalink
Huge commit. Adds better support for multiple versions and differing …
Browse files Browse the repository at this point in the history
…platforms/runtimes. Adds support for xUnit 2.1
  • Loading branch information
carlpett committed Jan 30, 2016
1 parent 6cf4c8b commit d867d01
Show file tree
Hide file tree
Showing 40 changed files with 1,554 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# xUnit TeamCity plugin
A xUnit runner for TeamCity. Supports tests written with xUnit 1.9.2 and 2.0.0, also supports wildcard include and exclude patterns.
A xUnit runner for TeamCity. Supports tests written with xUnit 1.9.2, 2.0.0 and 2.1.0, also supports wildcard include and exclude patterns.

# Download
Latest release is 1.0, get it here: https://github.com/carlpett/xUnit-TeamCity/releases/tag/1.0. Tested and developed on TeamCity 9.0, but should probably work on 8.0 as well.
8 changes: 4 additions & 4 deletions build/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<artifactId>xunitplugin</artifactId>
<groupId>se.capeit.dev</groupId>
<version>1.0</version>
<version>1.1.0</version>
</parent>
<artifactId>build</artifactId>
<packaging>pom</packaging>
Expand All @@ -18,17 +18,17 @@
<dependency>
<groupId>se.capeit.dev</groupId>
<artifactId>xunit-agent</artifactId>
<version>1.0</version>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>se.capeit.dev</groupId>
<artifactId>xunit-common</artifactId>
<version>1.0</version>
<version>1.1.0</version>
</dependency>
<dependency>
<groupId>se.capeit.dev</groupId>
<artifactId>xunit-server</artifactId>
<version>1.0</version>
<version>1.1.0</version>
</dependency>
</dependencies>
<build>
Expand Down
7 changes: 3 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>se.capeit.dev</groupId>
<artifactId>xunitplugin</artifactId>
<version>1.0</version>
<version>1.1.0</version>
<packaging>pom</packaging>
<properties>
<teamcity-version>9.0</teamcity-version>
Expand All @@ -21,13 +21,12 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>

</build>
<modules>
<module>xunit-server</module>
Expand Down
4 changes: 2 additions & 2 deletions xunit-agent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
<parent>
<artifactId>xunitplugin</artifactId>
<groupId>se.capeit.dev</groupId>
<version>1.0</version>
<version>1.1.0</version>
</parent>
<artifactId>xunit-agent</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>se.capeit.dev</groupId>
<artifactId>xunit-common</artifactId>
<version>1.0</version>
<version>1.1.0</version>
<scope>compile</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,27 @@
import jetbrains.buildServer.RunBuildException;
import jetbrains.buildServer.agent.BuildFinishedStatus;
import jetbrains.buildServer.agent.BuildProcess;
import jetbrains.buildServer.agent.BuildProgressLogger;
import jetbrains.buildServer.agent.BuildRunnerContext;
import jetbrains.buildServer.log.Loggers;
import org.jetbrains.annotations.NotNull;

abstract class FutureBasedBuildProcess implements BuildProcess, Callable<BuildFinishedStatus>
{
@NotNull private static final Logger LOG = Loggers.AGENT;
@NotNull protected final BuildProgressLogger logger;
private Future<BuildFinishedStatus> myFuture;

public FutureBasedBuildProcess(@NotNull final BuildRunnerContext context) {
this.logger = context.getBuild().getBuildLogger();
}

public void start() throws RunBuildException
{
try {
myFuture = Executors.newSingleThreadExecutor().submit(this);
LOG.info("Build process started");
} catch (final RejectedExecutionException e) {
LOG.error("Build process failed to start", e);
logger.error("Failed to start build!");
logger.exception(e);
throw new RunBuildException(e);
}
}
Expand All @@ -53,7 +59,7 @@ public boolean isFinished()

public void interrupt()
{
LOG.info("Attempt to interrupt build process");
logger.message("Attempt to interrupt build process");
myFuture.cancel(true);
}

Expand All @@ -62,14 +68,13 @@ public BuildFinishedStatus waitFor() throws RunBuildException
{
try {
final BuildFinishedStatus status = myFuture.get();
LOG.info("Build process was finished");
return status;
} catch (final InterruptedException e) {
throw new RunBuildException(e);
} catch (final ExecutionException e) {
throw new RunBuildException(e);
} catch (final CancellationException e) {
LOG.info("Build process was interrupted", e);
logger.exception(e);
return BuildFinishedStatus.INTERRUPTED;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
class XUnitBuildProcess extends FutureBasedBuildProcess {
private final AgentRunningBuild buildingAgent;
private final BuildRunnerContext context;
private final BuildProgressLogger logger;

public XUnitBuildProcess(@NotNull final BuildRunnerContext context) {
super(context);

this.context = context;
this.buildingAgent = context.getBuild();
this.logger = buildingAgent.getBuildLogger();
}

private String getParameter(@NotNull final String parameterName)
Expand All @@ -33,8 +33,14 @@ private String getParameter(@NotNull final String parameterName)
public BuildFinishedStatus call() throws Exception {
try {
String version = getParameter(StringConstants.ParameterName_XUnitVersion);
RunnerVersion runner = Runners.getRunner(version);
String runtime = getParameter(StringConstants.ParameterName_RuntimeVersion);
String platform = getParameter(StringConstants.ParameterName_Platform);
logger.message("Runner parameters { Version = " + version + ", runtime = " + runtime + ", platform = " + platform + "}");

File agentToolsDirectory = buildingAgent.getAgentConfiguration().getAgentToolsDirectory();
String runnerPath = new File(agentToolsDirectory, "xunit-runner\\bin\\" + version + "\\xunit.console.exe").getPath();
String runnerPath = new File(agentToolsDirectory, "xunit-runner\\bin\\" + version + "\\" + runner.getRunnerPath(runtime, platform)).getPath();
logger.message("Starting test runner at " + runnerPath);

String rawAssemblyParameters = getParameter(StringConstants.ParameterName_IncludedAssemblies);
String[] assemblies = rawAssemblyParameters.split(",|;|\n");
Expand All @@ -47,6 +53,8 @@ public BuildFinishedStatus call() throws Exception {
for (int i = 0; i < userExcludedAssemblies.length; i++)
excludedAssemblies[i + 1] = userExcludedAssemblies[i];

BuildFinishedStatus status = BuildFinishedStatus.FINISHED_SUCCESS;

// Find the files, and run them through the test runner
AntPatternFileFinder finder = new AntPatternFileFinder(assemblies, excludedAssemblies, true);
for(File assembly : finder.findFiles(context.getWorkingDirectory())) {
Expand All @@ -67,12 +75,16 @@ public void redirect(String s) {
}
});

process.waitFor();
int exitCode = process.waitFor();
if(exitCode != 0) {
logger.warning("Test runner exited with non-zero status!");
status = BuildFinishedStatus.FINISHED_FAILED;
}

logger.activityFinished(activityBlockName, DefaultMessagesInfo.BLOCK_TYPE_MODULE);
}

return BuildFinishedStatus.FINISHED_SUCCESS;
return status;
}
catch(Exception e) {
logger.message("Failed to run tests");
Expand All @@ -98,6 +110,7 @@ public void run() {
private String getCommandLineFlags(String version) {
// xUnit 2.0 changed format of commandline arguments from /flag to -flag.
// This is quite crude at the moment, but does the job.
// TODO: Migrate this into RunnerVersion or similar
char majorVersion = version.charAt(0);
if(majorVersion == '1')
return "/teamcity";
Expand Down
10 changes: 9 additions & 1 deletion xunit-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,16 @@
<parent>
<artifactId>xunitplugin</artifactId>
<groupId>se.capeit.dev</groupId>
<version>1.0</version>
<version>1.1.0</version>
</parent>
<artifactId>xunit-common</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package se.capeit.dev.xunittestrunner;

public abstract class RunnerVersion {
public final String version;
public String[] supportedRuntimes;
public String[] supportedPlatforms;

public RunnerVersion(String version, String[] supportedRuntimes, String[] supportedPlatforms) {
this.version = version;
this.supportedRuntimes = supportedRuntimes;
this.supportedPlatforms = supportedPlatforms;
}

public abstract String getRunnerPath(String runtime, String platform);

public String[] getSupportedRuntimes() { return supportedRuntimes; }
public String[] getSupportedPlatforms() { return supportedPlatforms; }
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package se.capeit.dev.xunittestrunner;

import java.util.*;

public final class Runners {
private static final TreeMap<String, RunnerVersion> AvailableRunners = new TreeMap<String, RunnerVersion>();

public TreeMap<String, RunnerVersion> getAllRunners() { return AvailableRunners; }
public Set<String> getSupportedVersions() { return AvailableRunners.descendingKeySet(); }
public Set<String> getSupportedRuntimes() {
HashSet<String> runtimes = new HashSet<String>();
for(Map.Entry<String, RunnerVersion> runner : AvailableRunners.entrySet()) {
for(String runtime : runner.getValue().supportedRuntimes)
runtimes.add(runtime);
}
return runtimes;
}
public Set<String> getSupportedPlatforms() {
HashSet<String> platforms = new HashSet<String>();
for(Map.Entry<String, RunnerVersion> runner : AvailableRunners.entrySet()) {
for(String platform : runner.getValue().supportedPlatforms)
platforms.add(platform);
}
return platforms;
}

public static RunnerVersion getRunner(String version) {
return AvailableRunners.get(version);
}

static {
AvailableRunners.put("1.9.2", new RunnerVersion("1.9.2",
new String[]{Runtime.dotNET35, Runtime.dotNET40},
new String[]{Platforms.x86, Platforms.MSIL}) {
@Override
public String getRunnerPath(String runtime, String platform) {
StringBuilder sb = new StringBuilder();
sb.append("xunit.console");
if (runtime.equals(Runtime.dotNET40))
sb.append(".clr4");
if (platform.equals(Platforms.x86))
sb.append(".x86");
sb.append(".exe");
return sb.toString();
}
});

AvailableRunners.put("2.0.0", new RunnerVersion("2.0.0",
new String[]{Runtime.dotNET45},
new String[]{Platforms.x86, Platforms.MSIL}) {
@Override
public String getRunnerPath(String runtime, String platform) {
StringBuilder sb = new StringBuilder();
sb.append("xunit.console");
if (platform.equals(Platforms.x86))
sb.append(".x86");
sb.append(".exe");
return sb.toString();
}
});

AvailableRunners.put("2.1.0", new RunnerVersion("2.1.0",
new String[]{Runtime.dotNET45},
new String[]{Platforms.x86, Platforms.MSIL}) {
@Override
public String getRunnerPath(String runtime, String platform) {
StringBuilder sb = new StringBuilder();
sb.append("xunit.console");
if (platform.equals(Platforms.x86))
sb.append(".x86");
sb.append(".exe");
return sb.toString();
}
});
}
}

final class Runtime {
public static final String dotNET35 = ".NET 3.5";
public static final String dotNET40 = ".NET 4.0";
public static final String dotNET45 = ".NET 4.5";
}
final class Platforms {
public static final String MSIL = "AnyCPU/MSIL";
public static final String x86 = "x86";
public static final String x64 = "x64";
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ public final class StringConstants {
public static final String RunTypeName = "xUnitRunner";
public static final String ToolName = "xunit-runner"; // Should mirror the xunit-runner artifactId

public static final String ParameterName_XUnitVersion = "xUnitVersion"; // Should mirror the xunit-runner artifactId
public static final String ParameterName_XUnitVersion = "xUnitVersion";
public static final String ParameterName_IncludedAssemblies = "includedAssemblies";
public static final String ParameterName_ExcludedAssemblies = "excludedAssemblies";
public static final String ParameterName_Platform = "runnerPlatform";
public static final String ParameterName_RuntimeVersion = "runnerRuntimeVersion";

// Getter methods for JSP pages
public String getParameterName_XUnitVersion() {
Expand All @@ -18,4 +20,10 @@ public String getParameterName_IncludedAssemblies() {
public String getParameterName_ExcludedAssemblies() {
return ParameterName_ExcludedAssemblies;
}
public String getParameterName_Platform() {
return ParameterName_Platform;
}
public String getParameterName_RuntimeVersion() {
return ParameterName_RuntimeVersion;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package se.capeit.dev.xunittestrunner;

import org.junit.Assert;
import org.junit.Test;

public class RunnersTest {
@Test
public void testCorrectVersionReturned() {
Assert.assertEquals("2.0.0", Runners.getRunner("2.0.0").version);
}

@Test
public void testCorrectRunnerPath() {
RunnerVersion runner = Runners.getRunner("1.9.2");
Assert.assertEquals("xunit.console.clr4.x86.exe", runner.getRunnerPath(Runtime.dotNET40, Platforms.x86));
Assert.assertEquals("xunit.console.clr4.exe", runner.getRunnerPath(Runtime.dotNET40, Platforms.MSIL));
Assert.assertEquals("xunit.console.x86.exe", runner.getRunnerPath(Runtime.dotNET35, Platforms.x86));
Assert.assertEquals("xunit.console.exe", runner.getRunnerPath(Runtime.dotNET35, Platforms.MSIL));
}
}
Loading

0 comments on commit d867d01

Please sign in to comment.