Working with slow modules in Maven is a problem. People will not build the module as often as they need and they will therefore not find problems as early as they could.
A solution could be to separate some of the slow stuff to a separate module. One separation can be to have a specific module for slow tests. This will, however, not solve the problem, that the module is too slow.
A solution to the problem could be to only include it in the execution when you invoke a specific Maven profile. This would separate the execution of a slow module from the execution of the rest, fast, modules.
Let me implement a simple example with two modules. There is the first module, the application, that we always want to build. It has fast unit tests and it is therefore not hindering to execute it often. Then there is the second module, the acceptance tests. It requires you to fire up your application before it can be executed. It is therefore dead slow. As a developer you will probably only want to execute the acceptance test module now and then.
Let me show you one way to achieve this.
Suppose that you need to do something from a Java program on a remote Linux server? How can you do that?
One thing we know is that Linux servers usually supports ssh and that you can do everything you need from a command line. In other words, you need a Java implementation of ssh so you can execute whatever you need on the remote host. Next problem is to either implement ssh yourself or find an implementation that you can use. If you decide not to implement ssh yourself, you will probably prefer a self contained implementation so you don’t have to include more dependencies than necessary. This is a good use case for Ganymed SSH-2 for Java. The only thing left is to:
- Include a dependency in your Maven, Gradle or Ant/Ivy project
- Implement whatever you want to do
I will show you one solution to 1 and 2 above.
Cucumber is very easy to run from Maven. How do you run it from Gradle?
The answer to this question is: It is as easy as to run it from Maven. Depending on your background, perhaps even easier. The reason for this is because we run Cucumber from a JUnit runner. That is as a unit test with a specific runner. Maven or Gradle really doesn’t have anything to do with this. It all boils down to the need for a Gradle project that can build a Java project. A Java project that has a unit test.
I have been using Maven for a long time. I used to use Ant and it took me a while to get used to Maven and accept the Maven way. Reading a blog post from Neal Ford Why Everyone (Eventually) Hates (or Leaves) Maven got me thinking. He talks about the popularity of 4GL, Fourth Generation Languages, during the 1990s and why they never really took off. The idea was great, but they were not able to solve the entire problem good enough. They solved perhaps 80% easily and the rest was harder and the last part was even harder to solve. The customers want this last part as well and that is the reason why we use general purpose programming languages today.
I used Paradox to build a system for a customer a long time ago. I was able to solve most of their problems.
One thing though, there was an error situation and the customer demanded a correct error message. My problem was that it was a system error that came from the runtime environment that I couldn’t control. My solution? To patch the binary that I delivered my application with. I replaced the error message with another message. I was lucky, the message I needed was one character shorter so the binary format was never changed. I am not sure that it was legal, I never asked Borland about it. But the error message became correct and the customer was happy and so was I.
Cucumber has a nice feature that will help you to use tables in your scenarios. The table can easily be converted to a list or a map that you can use in your step. I will show you a few examples that may help you get started.
This is the example I showed at the I T.A.K.E. Unconference 2014 in Bucharest. I created it for your convenience so you should be able to implement it yourself after the presentation.
Before we dive into the example, let me just recap what I am aiming for. I will show you how an example (or specification if you want) can be executed. The example is written in plain text and it is used as the basis for an execution. This example can later be relied upon for regression testing as well as living documentation.
How can you get the build directory in your maven plugin?
The answer to this question may seem simple, just refer to
./target in your plugin and everything should work. This works in the simple case. It does, however, not work when you are using you plugin in a multi module project. Your plugin will not know where it is executed and cannot refer to a subdirectory relative to the directory where Maven is invoked. It may be executed in a multi module build or a single module.
How can you pass a parameter to a unit test parametrised with JUnitParams? The answer is simple: As any other parameter.
Before I can try to motivate why you should use a tool, let me define what it is and what it does.
What is cucumber?
Cucumber is a tool for collaboration and testing. It is used to create examples of behaviour that are executable. Creating examples in a collaborative way emphasize close cooperation between business analysts, testers and developers. The examples they come up with can be used as acceptance tests for the system being developed. It can be used as a testing tool where the tests are defined in a business friendly language while still being executable.
Our goal is to create a common understanding of the problem and therefore simplify the communication between all parties involved. We would also like to get something that is possible to use for automating the verification of the resulting program. That is, use as a base for test automation of the system.
In my assignment as a Configuration Manager, CM, I need to script a lot of things. I also need to automate the execution. Most of the stuff I build is built using Maven. Some is built using Ant. Both Maven and Ant are easy to run from TeamCity. But none of them are very flexible when it comes to scripting. Maven isn’t designed for it and Ant is missing some features and get very verbose. The most important feature I am missing in Ant is repetition.
I saw a panel debate a while ago where three guys were discussing their favorite tools. The tools represented were Scala, Ruby and Groovy. One thing that I remembered from that session was that the Scala guy mentioned that he often used Ruby when scripting. My problem with using Ruby is that I don’t have control over my execution environment. I can’t install tools in it. I am not interested, either, because that wouldn’t scale very well since the installation done on our build servers are done manually. I can, however, expect that Maven and Ant will work.
Given that I can expect Maven to work, I decided to try to execute a Ruby script from Maven. It turned out to work very well. I was able to reduce the size of an Ant script with 50% on my first attempt. In my opinion, the readability increased a lot. I was able to write the script more or less as prose.
If you are interested, this is how I did.