Can't specify Cobertura datafile location for server running under Ant? - ant

I have an Ant build script that instruments some jar files, starts some servers using those jars files and then runs an integration test suite of junit tests against them.
I want to capture the cobertura.ser file from each server in a separate file.
The servers need to have their working directory set so they can pick up config files. It's a requirement of the system that the classpath must not be used to pick up these files.
Setting the net.sourceforge.cobertura.datafile system property allows the datafile to be set, and this works ok, until the "dir" property is set on the ant java task. Once dir is set, the server starts correctly, the test suite runs OK, but when the server shuts down no data file is written.
Here's a fragment of the build.xml:
<parallel>
<daemons>
<java fork="true" dir="src\main\resources\conf\my.server" classname="my.Server">
<sysproperty key="net.sourceforge.cobertura.datafile" file="target\cobertura.ser" />
<classpath>
...
</classpath>
<arg value="-server" />
</java>
...more servers...
...run junit tests...
</daemons>
</parallel>

The answer is to not run the servers as daemons. We were doing this so that the servers were automatically shut down when the junit task had completed, but in reality, the Cobertura instrumentation wasn't picking up the fact that the servers were shutting down and so never wrote out the various cobertura.ser files.
The solution was to remove the daemons task, and to add an explicit server shutdown mechanism which we could call from Ant once the tests were complete.

Related

Jenkins to run Jmeter script

Question is how to run a jmeter script using jenkins job.
Is there any pre-requisites like standard variable names and all.
I have heard that there are different plugins, some can just execute the script as it is while some other can take inputs from gui as well as provides report as chart or graph.
Also some posts says first we need to create ant programs and then need to call them from jenkins.
If possible, please detail the exact procedure and suitable plugin.
I use the following two methods:
You can run Jmeter in non-GUI mode using command line ("Execute Windows batch command" or "Execute Shell" build step in Jenkins job settings)
jmeter.bat -n -t path_to_your_jmx_script.jmx
Of course, you can do the same by launching Jmeter as a java application or within shell script.
By "Invoke Ant" build step.
This method provides you all the benefits of ant. So, just include jmeter in appropriate ant target in your build.xml file. Here is an example (jvmarg and jmeterarg are not required):
<target name="test" depends="clean">
<jmeter jmeterhome="${jmeter-home}"resultlogdir="results/jtl">
<testplans dir="scripts" includes="*.jmx"></testplans>
<jmeterarg value="-Jbackend=${env.Backend_Address}"/>
<jvmarg value="-Xmx512m"/>
<jvmarg value="-Xdebug"/>
</jmeter>
</target>
And that's how you can generate nice report:
<target name="report" depends="test">
<xslt classpathref="xslt.classpath"
basedir="results/jtl"
destdir="results/html"
includes="*.jtl"
style="${jmeter-home}/extras/jmeter-results-detail-report_21.xsl">
<param name="showData" expression="${show-data}"/>
</xslt>
<copy file="${jmeter-home}/extras/expand.png" tofile="results/html/expand.png"></copy>
<copy file="${jmeter-home}/extras/collapse.png" tofile="results/html/collapse.png"></copy>
</target>
Regarding Jenkins plugins - the only one I know (and use) is Performance Plugin that can mark your build as failed/passed based on Jmeter results and generate nice graphs.
This site has the detailed information on Jmeter + Ant + Jenkins integration.
Other than running the test, you might also be interested in generating reports, charts and mailing the results.
Check here:
http://www.testautomationguru.com/jmeter-continuous-performance-testing-part2/
Jenkins doesn't provide any plugins to execute a JMeter test, it is up to you how you will launch it, the choices are in:
Command-line non-GUI mode
Ant task
Maven plugin
So you need to add a build step which will trigger JMeter test execution using one of above approaches. Also you can add Performance Plugin as a post-build action in order to be able to visualise performance trends and set pass and fail criteria.
See Continuous Integration 101: How to Run JMeter With Jenkins article for detailed walkthrough.

Is it possible to copy an empty directory using ant ftp task

Running in to ussue using FTP task from Apache Ant. Finding that an empty directory is not being created in the target location. Is there way to force the transfer to create the directory? this is representative of the task specified in my ant build script. the first three substitutions are obvious the 4th is the source directory and the 5th is the target directory.
<ftp action="get"
server="${Server}"
userid="${User}"
password="${Password}"
passive="true"
remotedir="${DependenciesDirectory}">
<fileset dir="${bldSrvDependenciesDirectory}">
<include name="**/**" />
</fileset>
</ftp>
This is a known limitation of ant ftp and scp task. The simple workaround is to make sure every directory contains at least some dummy placeholder file.

Calling Ant from Nant without batch

We have an automated build process that uses Nant scripts, and we just inherited a Java project that has an existing, working Ant script. I have searched all over and it seems most people use a batch file to call Ant scripts from Nant. This seems a little hacky to me. Is there a way to call Ant scripts directly from Nant in task format?
This similar question addresses it with a batch file but I want to do it without.
<!-- calling the Ant build Process-->
<target name="AntBuildProcess" description="Created to call the Ant build during this NAnt build process" >
<echo message="Starting the Ant Build Process..." />
<exec program="ant" commandline='-buildfile YourAntBuild.xml' failonerror="true"/>
</target>
Then during your Build process, you just call this target at the point you need it to be built. <call target="AntBuildProcess" />
Ant is a batch file. Take a look, and you'll see a file called ant.bat in the %ANT_HOME%\bin directory.
Ant is actually a Java program, so you could launch it from the java command by running the class org.apache.tools.ant.launch.Launcher which is basically what the ant.bat file is doing.
However, why reinvent the wheel? The ant.bat runs the Java command the right way, gives you options to change the way it's executed, and makes sure everything is setup correctly.
Addendum
I see, Nant, unlike Ant, will always call cmd.exe and use suffixes and %PATHEXEC% to figure out if something is a batch script or other type of script. Thus, if you want to run Ant using Ant as a batch script via <exec/> you would do this:
<exec executable="cmd.exe"
dir="${working.dir}">
<arg value="/c"/>
<arg value="ant.bat"/>
</exec>
However, in Nant you can simply do it this way:
<exec program="ant"
workingdir=${working.dir}"/>

Runnable jar file without ant java task - how is this possible?

I've inherited some code from a previous developer, which gets built using Ant into an executable jar file that runs by double clicking. The application runs, but under some conditions crashes with an OutOfMemoryError. To investigated this, I'd like to add the -XX:+HeapDumpOnOutOfMemory jvm arg to the Ant buildfile, and as I understand it, the <jvmarg value="-XX:+HeapDumpOnOutOfMemory" /> element needs to go under a <java ...> task. However, there is no <java ...> task to be found in this or any other Ant buildfiles in this code base.
How is this even possible? How can the jar file be executable without a <java ...> task?
I'm asking primarily to find out what in fact makes my jar file executable so that I can figure out where to put that <jvmarg /> element to debug the OOME.
Thanks!
A <java> task doesn't create an executable jar file. It executes a Java program.
I don't think it's possible to specify VM parameters when starting an executable jar file by double-clicking on it. If you want to pass VM parameters, open a command prompt and execute the jar this way:
java -XX:+HeapDumpOnOutOfMemory -jar nameOfTheJar.jar
Your jar is executable because it has a Main-Class defined in the META-INF/MANIFEST.MF file. Double clicking it to run doesn't do anything with Ant. Ant is simply used to package the jar.
In order to add the parameter and still launch via a double click you could create a shortcut that runs the command in JB Nizet's answer

How to load an optional task into ant without -lib or global installation?

I want to use the FTP task in ant, and I have found the appropriate jar files and got everything working fine. I have put the jar files in a "libs" directory alongside the other files used in the build. The only problem is that the user must run "ant -lib commons-net-ftp-2.0.jar" to make a build; I would really prefer that it were possible to just run "ant" with no arguments.
Reading the ant optional tasks intallation page, I see that there are five ways one can load up extra libraries in ant, and none of them are really what I'm looking for. I do not want to force the user to make any modifications to their system to run this task; it should be possible to just load it from the "libs" directory inside of our product's source folder. So that means setting the global CLASSPATH is also out (which is a bad idea anyways).
The last option, as noted in the documentation, is the preferred approach... loading the jarfiles individually from the build script itself. I have done this in the past with the ant-contrib tasks and JUnit, and would like to do that here, but I don't see how I can accomplish this. The FTP task doesn't support a nested classpath element, and I don't know the XML resource I would need to load this library via a taskdef. How can I load the libraries from within ant?
Edit: In response to the answers and questions which have been posted here so far, I'm using ant 1.7.1. Making an ftp taskdef definitely does not work; that throws the following error:
BUILD FAILED
/my/path/build.xml:13: taskdef class org.apache.tools.ant.taskdefs.optional.net.FTP cannot be found
Perhaps this is because the classname is wrong. How exactly do I find the classname I'm supposed to use if I only have a jarfile? It's not documented anywhere, and I couldn't find anything in the jar itself resembling that path.
The problem you are having is due to the different class-loaders in use. The Commons Net classes must be loaded by the same class-loader that loads the FTP task. Because the FTP task is loaded by Ant on start-up, you need to add the Commons Net to Ant's classpath so that it is loaded by the same class-loader. That's why the documentation gives you 4 different ways to do this.
I agree that none of them are ideal (the CLASSPATH environment variable being the worst). One way around this is to supply a shell script with your project that invokes Ant and passes the apporpriate -lib argument. You then get people to use this rather than invoking Ant directly. In fact, you could deviously name it 'ant' so that it gets run instead of the existing 'ant' on the path (this only works if the current directory is on the path, ahead of other directories).
The fifth option in the documentation is great in theory. They finally fixed the class-loading problems in 1.7.0. Unfortunately, as you mention, nobody retro-fitted the FTP task to take a classpath. You could try submitting an enhancement request, but this won't help in the short term.
There is one other option, which isn't any better than the others. Instead of making sure that the Commons Net classes are loaded by the class-loader that loads the FTP task, you could make sure that the FTP task is loaded by the class-loader that loads the Commons Net classes. To do this you have to remove the ant-commons-lib.jar file from the 'lib' directory of the Ant installation. This means that the FTP task won't get loaded on start-up. This is actually why the optional tasks are broken up into so many separate JARs - so that they can be individually removed. Put this JAR file alongside the Commons Net JAR file so that it can be loaded at the same time. Then you can do something like this (I tried this and it works):
<taskdef name="ftp"
classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
<classpath>
<pathelement location="${basedir}/lib/ant-commons-net.jar"/>
<pathelement location="${basedir}/lib/commons-net-2.0.jar"/>
</classpath>
</taskdef>
<ftp server="yourserver.com"
userid="anonymous"
password="blah">
<fileset dir="somedirectory"/>
</ftp>
But this is probably a worse option than just using the -lib switch (with or without a wrapper script). The only other thing I can think of is to try to find a third-party FTP task to use instead of the default one.
I have a solution:
you can download a new "classloader" task from http://enitsys.sourceforge.net/ant-classloadertask/ and load it whith:
<taskdef resource="net/jtools/classloadertask/antlib.xml"
classpath="XXX/ant-classloadertask.jar"/>
Naw can do things like loading classes with the same classloader that ant use for his task:
<classloader loader="system" classpath="XXX/commons-net-2.0.jar"/>
or "loader="project""
Then you definde your task:
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP"/>
and go :-)
So I succeeded in doing this for the ant-salesforce.jar that you get when trying to do salesforce work (fun...)
Check to see if the jar has an xml file in it that looks something like this:
<antlib>
<typedef name="compileAndTest" classname="com.salesforce.ant.CompileAndTest"/>
....
</antlib>
Then in ant give it a taskdev that reads that file from inside the given jar, like this:
<taskdef resource="com/salesforce/antlib.xml" classpath="lib/ant-salesforce.jar" />
Hope that helps some.
Ah, man, this is just so nasty. I run ant from eclipse. I don't want to reconfigure ant in eclipse for new workspaces, so here's what I decided to do, to decouple running the task and configuring ant. I extracted the ftp task to a separate build file. Next I added a native call to the command line to start a completely new ant process with the required libraries on the path:
<target name="deploy-ftp">
<exec command="ant">
<arg line="-buildfile ftp.xml deploy-ftp -lib lib/ant"/>
</exec>
</target>
Now the master build file can be run without any special arguments and no modifications are required to the ant installation. It's nasty though, since the ftp task runs in a completely clean environment. None of the properties and paths from the master build file are available. Luckily I had all of these in a separate property file anyway, so I only needed a single import.
I would like to add a big thanks to Dan Dyer. Without your extensive explanation of what's going on behind the scenes, I wouldn't have found this solution.
Will this work assuming libs is directly under you project's base directory
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
<classpath>
<pathelement location="${basedir}\libs\commons-net-1.4.0.jar"/>
</classpath>
</taskdef>
Your users all have ant installed on their machines but you can't / don't want to make them add the FTP jar? Can you bundle ant with your project make tasks that call YOUR ant bundle, with the jars placed so it'll work as follows?
<taskdef name="ftp" classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
<classpath>
<pathelement location="\lib\commons-net-1.4.0.jar"/>
</classpath>
</taskdef>
<target name="testFtp">
<ftp server="blah" userid="foo" password="bar">
<fileset file="test.file" />
</ftp>
</target>

Resources