I'm trying to set up an ANT build script which compile code, compile tests, run unittests and then build. These are all done through separate targets with dependencies i.e.
<target name="compile">
<javac>...
</target>
<target name="compile-tests" depends="compile">
<javac>...
</target>
<target name="unittest" depends="compile-tests">
<junit...
<test ...
<fail if="tests.failed" ..
</target>
<target name="build" depends="compile, unittest">
</target>
Each 'test' inside the 'junit' task focuses on one part of the application, (typically package by package) and points to a Junit TestSuite. This set up allows for all tests to be run when a build is called but this isn't ideal for day-to-day development.
I would like to be able to do 2 things:
Run all the tests in a build (like the setup shown above)
Run tests individually from ant
My solution for (2) was to use multiple antcall tasks which isn't really best practice. During these calls different properties were set to run all the tests as they each required a different property:
<!-- test package p2 with ant unittest -Dtest.p2=true -->
<target name="unittest" depends="compile-tests">
<junit...
<test if="test.p1" ...
<test if="test.p2"
<fail if="tests.failed" ..
</target>
<target name="unittestall">
<property name="test.p1" value="true"/>
...
</target>
<target name="build" depends="compile, unittest">
<antcall target="unittestall" />
<antcall target="clean" />
<antcall target="compile" />
</target>
This gave the granularity I required but meant alot of work was duplicated and ant's dependency features weren't being used to their full.
So my question is:
How can I best set up ANT and Junit so that all tests can be run as part of a build AND so that individual tests can be run?
Thankyou :)
from Joshua England
p.s. ANT 1.8 and Junit 4.10 :)
Something like this?
<target name="unittest-p1"></target>
<target name="unittest-p2"></target>
<target name="unittest-p3"></target>
<target name="unittest" depends="unittest-p1, unittest-p2, unittest-p3/>
You could then run all the tests by passing the unittest target:
ant unittest
(or any target which depends on unittest)
And you could run any individual test of set of tests by invoking the appropriate target, e.g.
ant unittest-p1
If you would end up with a lot of duplication in multiple junit targets, you could tidy that up by putting all the common stuff into a macrodef.
Related
I want to run unit tests using MSBuild. Here is how I invoke msbuild today:
msbuild MySolution.sln
Instead, I want to use an MSBuild project file called "MyBuild.proj" like this:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5" DefaultTargets="Build">
<Target Name="Build">
<ItemGroup>
<SolutionToBuild Include="MySolution.sln" />
<TestContainer Include="..\Output\bin\Debug\*unittests.dll"/>
</ItemGroup>
</Target>
</Project>
And then call this command line:
msbuild MyBuild.proj
For some reason, when I do that the command succeeds immediately and the build doesn't even happen. I fear I must be missing something very obvious as I am new to MSBuild.
I suppose I really have 2 questions:
Why doesn't this even build my solution
Is the "TestContainer" element correct for executing my tests
Thanks!
You havent supplied any task to actually do anything,
inside your build target you need a call to an msbuild task, your example becomes:
<Target Name="Build">
<ItemGroup>
<SolutionToBuild Include="MySolution.sln" />
<TestContainer Include="..\Output\bin\Debug\*unittests.dll"/>
</ItemGroup>
<MSBuild Projects="#(SolutionToBuild)"/>
</Target>
this specifies what projects you actually want msbuild to build.
See:http://msdn.microsoft.com/en-us/library/vstudio/z7f65y0d.aspx for more details and the parameters it takes.
Thats part one.
As for part 2? what testing framework are you using? If using mstest id try wrapping the commandline mstest.exe in an msbuild exec statement to get it to run and execute the tests. See an example here:http://social.msdn.microsoft.com/Forums/en-US/msbuild/thread/cb87a184-6589-454b-bf1c-2e82771fc3aa
I am trying to call the Publish target every time I build my WPF app. I have tweaked the .csproj file to include this:
<Target Name="AfterBuild">
<Message Text="Running AfterBuild..." />
<MSBuild Projects="$(MSBuildProjectFullPath)" Properties="Configuration=$(Configuration); PublishDependsOn=" Targets="Publish" />
</Target>
When I run this from the command line, I see the message that it is 'Running AfterBuild...' but nothing happens. If I remove the '; PublishDependsOn=' from the Properties of the MSBuild task, I get a circular reference error.
What magic am I missing here?
OK, I figured out how to do what I want to do. Instead of trying to explicitly call Publish in AfterBuild, I just added it to the DefaultTargets of the project. Now it calls Build then Publish.
<Project ToolsVersion="4.0" DefaultTargets="Build;Publish" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
I'm working on an internal ivy repository with a decent number of projects under it, each with many revisions. I would like to make a dependency report for the entire repository showing which versions of which artifacts depend on which revisions of other artifacts. Obviously it isn't too difficult to make a script to parse the published ivy xml files, but if this functionality exists already I'll use that. Something like the repreport task would be nice, but for a whole repo.
My main goal here is to get a report of artifacts that are not referenced by any other artifacts so as to make a list of candidates for removal from the repo.
So, does ivy have any way to build a dependency report against and entire repository?
Edit: Working through this, it looks like ivy:repreport is the way to go.
Here is my build.xml file:
<project name="Report Build" xmlns:ivy="antlib:org.apache.ivy.ant" basedir=".">
<property name="ivy.version" value="2.2.0"/>
<property name="ivy.home" value="${user.home}/.ivy2"/>
<target name="fetch-ivy" unless="offline" description="Install Ivy if it doesn't already exist">
<mkdir dir="${ivy.home}"/>
<get
src="http://repo2.maven.org/maven2/org/apache/ivy/ivy/${ivy.version}/ivy-${ivy.version}.jar"
dest="${ivy.home}" usetimestamp="true"/>
</target>
<target name="init-ivy" depends="fetch-ivy" unless="ivy-initialized">
<path id="ivy.lib.path">
<fileset dir="${ivy.home}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml" uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
<property name="ivy-initialized" value="yes"/>
</target>
<target name="report" depends="init-ivy">
<ivy:settings file="ivy-settings-report.xml" id="report.ivy.settings"/>
<ivy:repreport settingsref="report.ivy.settings"/>
</target>
</project>
And here is my ivy settings file:
<?xml version="1.0" encoding="UTF-8"?>
<ivy-settings>
<settings defaultResolver="main"/>
<resolvers>
<chain name="main">
<url name="internalartifacts" m2compatible="false">
<artifact
pattern="http://internalartifacts.local/[organization]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"/>
<ivy pattern="http://internalartifacts.local/[organization]/[module]/[revision]/ivy-[revision].xml"/>
</url>
</chain>
</resolvers>
</ivy-settings>
The documentation for repreport says:
To generate a xml report for all the latest versions of all the
modules in your repository:
<ivy:repreport />
Limitation: this task requires to be able to browse the repository,
and is thus limited to resolvers supporting repository listing. In
particular, it means it doesn't work to report all organizations in a
repository using m2compatible mode. Moreover, to be able to list
organizations, this task requires an [organisation] token in the
resolver(s) used.
So this should totally work.
As mentioned in the comment:
It is important that your repository has ivy.xml files for the artifacts in it. Otherwise ivy cannot recognize the dependencies between the artifacts and your report will be empty.
I have a Java project with some unit tests written using JUnit. Recently some new unit tests have been added that are written in groovy (also using JUnit) as it's easier to make those
more expressive and generally easier to read. It also allows us to use the spock framework.
The project is build and tested with ant.
Before the groovy classes were added unit tests were run using the following ant task:
<target name="test" depends="test-compile">
<junit printsummary="yes">
<classpath>
<path refid="test.classpath"/>
</classpath>
<formatter type="plain"/>
<batchtest fork="yes" todir="${test.dir}/report">
<fileset dir="${test.dir}/unit" includes="**/*.java"/>
</batchtest>
</junit>
</target>
However, this approach does not work for groovy tests as those are in *.groovy files and the JUnit Ant task, understandably, does not recognise them in the fileset.
The alternative approach is to use *.class files for the batchtest fileset like this:
<batchtest fork="yes" todir="${test.dir}/report">
<fileset dir="${test.dir}/${build.dir}">
<include name="**/*Test*.class" />
</fileset>
</batchtest>
This generates false negatives as closure class files are also included so a possible workaround is to exclude those files.
<batchtest fork="yes" todir="${test.dir}/report">
<fileset dir="${test.dir}/${build.dir}">
<include name="**/*Test*.class" />
<exclude name="**/*$*.class" />
</fileset>
</batchtest>
Is there a better way to identify test classes fo the junit ant task? Perhaps one based on reflection and the #Test attribute as manually listing all the test classes (which would work perfectly well) is not really a maintainable solution. Something like the SpecClassFileSelector from the Spock framework.
what about changing the include pattern to *Test rather than *Test*
as #jon-skeet suggested here.
This way it will not match the anonymous closure classes.
you'll have to rename your existing classes and ask the developers to follow this pattern.
Take a look at:
http://www.ibm.com/developerworks/java/library/j-pg11094/
There's a groovyc ant taskdef for compiling the groovy test cases and running them. The example there is Maven, but it shouldn't be too hard to adapt it to do what you want.
Can't you just write something like this?
<fileset dir="${test.dir}/unit" includes="**/*.java,**/*.groovy"/>
Just wondering if someone could help me with some msbuild scripts that I am trying to write. What I would like to do is copy all the files and sub folders from a folder to another folder using msbuild.
{ProjectName}
|----->Source
|----->Tools
|----->Viewer
|-----{about 5 sub dirs}
What I need to be able to do is copy all the files and sub folders from the tools folder into the debug folder for the application. This is the code that I have so far.
<ItemGroup>
<Viewer Include="..\$(ApplicationDirectory)\Tools\viewer\**\*.*" />
</ItemGroup>
<Target Name="BeforeBuild">
<Copy SourceFiles="#(Viewer)" DestinationFolder="#(Viewer->'$(OutputPath)\\Tools')" />
</Target>
The build script runs but doesn't copy any of the files or folders.
Thanks
I was searching help on this too. It took me a while, but here is what I did that worked really well.
<Target Name="AfterBuild">
<ItemGroup>
<ANTLR Include="..\Data\antlrcs\**\*.*" />
</ItemGroup>
<Copy SourceFiles="#(ANTLR)" DestinationFolder="$(TargetDir)\%(RecursiveDir)" SkipUnchangedFiles="true" />
</Target>
This recursively copied the contents of the folder named antlrcs to the $(TargetDir).
I think the problem might be in how you're creating your ItemGroup and calling the Copy task. See if this makes sense:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
<YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
</PropertyGroup>
<Target Name="BeforeBuild">
<CreateItem Include="$(YourSourceDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="#(YourFilesToCopy)"
DestinationFiles="#(YourFilesToCopy->'$(YourDestinationDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
</Project>
I'm kinda new to MSBuild but I find the EXEC Task handy for situation like these. I came across the same challenge in my project and this worked for me and was much simpler. Someone please let me know if it's not a good practice.
<Target Name="CopyToDeployFolder" DependsOnTargets="CompileWebSite">
<Exec Command="xcopy.exe $(OutputDirectory) $(DeploymentDirectory) /e" WorkingDirectory="C:\Windows\" />
</Target>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<YourDestinationDirectory>..\SomeDestinationDirectory</YourDestinationDirectory>
<YourSourceDirectory>..\SomeSourceDirectory</YourSourceDirectory>
</PropertyGroup>
<Target Name="BeforeBuild">
<CreateItem Include="$(YourSourceDirectory)\**\*.*">
<Output TaskParameter="Include" ItemName="YourFilesToCopy" />
</CreateItem>
<Copy SourceFiles="#(YourFilesToCopy)"
DestinationFiles="$(YourFilesToCopy)\%(RecursiveDir)" />
</Target>
</Project>
\**\*.* help to get files from all the folder.
RecursiveDir help to put all the file in the respective folder...
This is the example that worked:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MySourceFiles Include="c:\MySourceTree\**\*.*"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy
SourceFiles="#(MySourceFiles)"
DestinationFiles="#(MySourceFiles->'c:\MyDestinationTree\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
source: https://msdn.microsoft.com/en-us/library/3e54c37h.aspx
This is copy task i used in my own project, it was working perfectly for me that copies folder with sub folders to destination successfully:
<ItemGroup >
<MyProjectSource Include="$(OutputRoot)/MySource/**/*.*" />
</ItemGroup>
<Target Name="AfterCopy" AfterTargets="WebPublish">
<Copy SourceFiles="#(MyProjectSource)"
OverwriteReadOnlyFiles="true" DestinationFolder="$(PublishFolder)api/% (RecursiveDir)"/>
In my case i copied a project's publish folder to another destination folder, i think it is similiar with your case.
Did you try to specify concrete destination directory instead of
DestinationFolder="#(Viewer->'$(OutputPath)\\Tools')" ?
I'm not very proficient with advanced MSBuild syntax, but
#(Viewer->'$(OutputPath)\\Tools')
looks weird to me. Script looks good, so the problem might be in values of $(ApplicationDirectory) and $(OutputPath)
Here is a blog post that might be useful:
How To: Recursively Copy Files Using the <Copy> Task
Personally I have made use of CopyFolder which is part of the SDC Tasks Library.
http://sdctasks.codeplex.com/
The best way to recursively copy files from one directory to another using MSBuild is using Copy task with SourceFiles and DestinationFiles as parameters. For example - To copy all files from build directory to back up directory will be
<PropertyGroup>
<BuildDirectory Condition="'$(BuildDirectory)' == ''">Build</BuildDirectory>
<BackupDirectory Condition="'$(BackupDiretory)' == ''">Backup</BackupDirectory>
</PropertyGroup>
<ItemGroup>
<AllFiles Include="$(MSBuildProjectDirectory)/$(BuildDirectory)/**/*.*" />
</ItemGroup>
<Target Name="Backup">
<Exec Command="if not exist $(BackupDirectory) md $(BackupDirectory)" />
<Copy SourceFiles="#(AllFiles)" DestinationFiles="#(AllFiles->
'$(MSBuildProjectDirectory)/$(BackupDirectory)/%(RecursiveDir)/%(Filename)%
(Extension)')" />
</Target>
Now in above Copy command all source directories are traversed and files are copied to destination directory.
If you are working with typical C++ toolchain, another way to go is to add your files into standard CopyFileToFolders list
<ItemGroup>
<CopyFileToFolders Include="materials\**\*">
<DestinationFolders>$(MainOutputDirectory)\Resources\materials\%(RecursiveDir)</DestinationFolders>
</CopyFileToFolders>
</ItemGroup>
Besides being simple, this is a nice way to go because CopyFilesToFolders task will generate appropriate inputs, outputs and even TLog files therefore making sure that copy operations will run only when one of the input files has changed or one of the output files is missing. With TLog, Visual Studio will also properly recognize project as "up to date" or not (it uses a separate U2DCheck mechanism for that).