Wednesday, June 15, 2016

Make your tests fast again !

Spring framework is quit slow at startup stuff, regardless of what top responders on stack overflow seem to think.


Over the years we have developed quite a few tactics to work with this, like starting the application in Unit @BeforeClass or even a JUnit run listener. This sort-of worked with old-style monolithic applications but it was usually a quite poor approach; there are all sorts of reasons for wanting to start slightly different permutations of your application, and why can't just spring be fast ?

As of spring 4.2 you can do this:
  return new AnnotationConfigApplicationContext() {

   @Override protected void resetCommonCaches() {
   }
  }

This will dramatically speed up creation of your subsequent spring contexts.

There are a couple of possible gotchas here; since this will re-use cached type information (cached in static scope) form your previous test run, much increasing the startup speed of a subsequent spring context within the same forked process. Moving all your IT's to a single project is always smart, since class loading and static initialization is the real killer in terms of startup time.

The method in AbstractApplicationContext (the base class) does this:
 protected void resetCommonCaches() {
  ReflectionUtils.clearCache();
  ResolvableType.clearCache();
  CachedIntrospectionResults.clearClassLoader(getClassLoader());
 }


Happy hacking !

Tuesday, March 4, 2014

Break the bloated library cycle with Java 8

Most of us have, at some point in time, wondered why all successful java libraries tend to "bloat" by adding new stuff all the time. Spring is a great example. Why on earth is there spring-jdbc, spring-transaction or even spring-web ?

Apart from the obvious market-wise need for a companies to appear as a continuous sources of innovation (investors like that), there are some technical issues involved too. This post looks at how java8 can change some of the dependency issues; it may even change how you do java7 right now.

Java7


The dilemma: A class/library wishes to reuse external services, which introduces dependencies.

public class MyClass {
    private ExternalDependency1 ed1;
    private ExternalDependency1 ed2;
   public int doSomething(String input){
       return ed1.calculate( ed2.transform( input));
   }
}

Now this is the classical reason why need to make *our* module depend on something external, ExternalDependency1 and ExternalDependency2 are defined in another project. This is basically the technical reason why we have 280 different "spring" projects; they all tie in with their different dependencies.

Java8 to the rescue

In java8, we can easily move the declaration of the required type *into* MyClass, which makes it self-contained with respect to dependencies:

public class MyClass {

public interface InternalDependency1 {

int calculate(String source);
}
public interface InternalDependency2 {
String transform(String source);
}
private InternalDependency1 id1;
private InternalDependency2 id2;
public MyClass(InternalDependency1 id1, InternalDependency2 id2) {
this.id1 = id1;
this.id2 = id2;
}
public void doSomething(String input){
id1.calculate( id2.transform( input));
}
}

At first glance, this seems like just additionally bloating the code. We need to look at the use before it all becomes clear:

ExternalDependency1 ed1 = new SomeObject1();
ExternalDependency2 ed2 = new SomeObject1();
MyClass mc = new MyClass( ed1::calculate,         ed2::transform);

Now this is where the subtle magic happens; any method that matches the *shape* of the calculate or transform method will be autoboxed into something that can be *used* as InternalDependency1/2.

With this one magic little change, MyClass suddenly lost all its external dependencies.

What about java.util.function.Function ?


Some of you will notice that I am using 1 method interfaces instead of the generic java.util.function.Function class. There are several reasons for this:

A) It is an explicit type that will some day provide IDE support. Current IDE support is somewhat sketchy, but this will improve.
B) "MyClass" is a library component that is expected to have clients; the "cost" of these interfaces making the external contract of "MyClass" 100% clear is probably worth it in the long run.
C) This is java5/6/7 compatible, although the java7 client will have a slightly less cool client api (anonymous inner class galore)
D) If you use Function, the only thing expressing the intention of the function will be the local variable name; in this case id1 and id2. This makes our java code all javascripty; much as I love javascript I am a little sceptical about too this in java; at least for "library" style code.




Friday, November 4, 2011

100 days of Whole30, my personal summary

We interrupt the general nerdiness of this blog with a little experience report of my whole30 lifestyle change. A 30 day "diet" designed to improve your health and maybe loose some weight in the process (http://whole9life.com/).

I started at the end of July, weighing a solid 96,5kg, probably 20cm too short for that weight - and I'm 42 so it's getting sooo hard to get rid of.

Whole30 is about eating natural ingredients, preferably organic. No sugar, alcohol, wheat or anything containing any "E"'s. Just 3 daily meals of real, natural food. I've been 100% faithful in the whole period, eating organic and the highest quality I can find here in Oslo.  All along these 100 days I've been running 7 km three times a week.

Day for day, this is what happened:

Day 5: Out shopping at IKEA with wife, I realize I feel really energized; damn good! Feeling good at IKEA is a first for me, ever.

Day 8: My sense of smell returned 100%.
   Having chronic tonsil & sinus infections, I removed tonsils and surgically opened sinus canals 3 years ago. In those three years, I have had like 25% normal sense of smell (I could wash the toilets with 20% chlorine and not notice it!). All of a sudden I started smelling all kinds of things.

Day 10: My blood pressure goes up.
   I've always been borderline high blood pressure, most of the time *at* the treatment limit. Unfortunately I seem to not tolerate /any/ blood pressure medication, my body seems to reject them each time I use them. So, in line with doctor's orders I start with medicine for enough to get my pressure down (5 days, give or take).

Day 14: I am quite angry
   My wife complains that I am easily agitated. I know this too, but I also feel it is different from the insane rage I could get if I followed something like the cambridge diet.


Day 16: I stop blood pressure medication, back at my "usual" borderline level. (This is according to doctor's orders; please follow your own doctor on this! If I stay on /any/ blood pressure medication for 14 days I collapse)

Day 18: I feel great.

Day 20: My blood pressure drops by 15 (over/under). I have never had this low blood pressure, ever. (This has no connection to the medication I quit a few days earlier, the medication only brings me immediately below the treatment treshold) My new blood pressure is "normal." I've /never/ had "normal"  ever.


Day 25: Wife still complains I'm easily agitated

Day 30: I'm about 5 kg down

Day 40-50: I feel great. My mood is fantastic. Colleagues at work start commenting that I'm in a fantastic mood. They've been informed and curious since day 1, but I think it's becoming clearly obvious to everyone that there is change going on.

Day 60: Wife says I seem to be happy.

Day 70: I feel fucking marvellous, and we're talking mental state. I've never tried cocaine, but this must be what it's like. (Ok, probably not, but this is healthy!)

Day 80: Wife says I seem extremely happy.

Day 100: Officially "done" with the "diet" part. Drinking my first glass of wine & eating sushi. I'm not sure what I'll do next but today I added organic red wine and sushi to my diet; if I can add those two things I'll be satisfied for quite some more time. 10kg down.

There's one thing I'm still unsure about; and that's ketosis. I seem to be going in & out of ketosis all of the time, and I'm probably eating too much or too little carbs. There's a lot of transitional issues involved in going into ketosis (bad breath being perhaps the most notable). It seems like ketosis is good for losing weight, but I assume it won't be necessary now that I'm approaching an acceptable weight.

I know my colleagues will be starting whole30 soon. In thirty days you can find out what impact your current eating has on your health. How can you not take just 30 days ? I took 100 ;)

Tuesday, August 9, 2011

Your new password

I was fed up with having a zillion passwords. Worst of all, we don't have any insight into what kind of security the websites you access employ, so happy anarchists like LulzSec and Anonymous can run away with your master password if you're not careful.

So instead of a password, I ended up with the following algorithm;

  • Second letter in the domain name (Or last letter), in uppercase
  • Constant part. Starting with one or more captialized letters, ending with a digit. 6 chars or more. You may choose to look at http://www.baekdal.com/tips/password-security-usability for this bit.
  • A digit 1 (increase this for sites that require password change)
  • The number of vowels (or consonants, or [A-F] or whatever in the domain name)
  • First letter in domain name, lowercase


The constant part should probably contain at least one "special" character like % { or whatever, simply because sites may start requiring this. But think about accessibility for this character on phones etc.

A couple of key points about this algorithm: All digits are grouped together, as for capital letters. Some devices (iPhone etc) require additional touches to switch to upper case or numeric keyboards, so group them together.

The "domain name" is the last word before .com/.org.

I keep the constant part about 6 chars, to make 10 digits total. You might consider going for 12 total.

In some places you may be likely to give away your password (this may happen to me at work sometimes). In those cases you can use a different constant-part or simply a totally different password, at least I always know these things up-front.

Think it sounds like a hassle ? I feel the hassle every time I encounter a site where I haven't used this pattern yet, you get used to it.... This password should be strong enough to last the rest of my life. (Lol, I know that's not going to happen).

Monday, April 18, 2011

Watch that @Autowired

Those who follow me on Twitter, will see that I just submitted a patch for SPR-6870. Great patch if you're running something like a web-based application with lots of non-singleton scoped components. You might save a server or more by applying that patch and the spring context starts quite a bit faster too.

So while you're waiting 20 minutes for spring to compile, just look out for one more thing:

Don't autowire into arrays/collections unless the containing component is a singleton. Spring does not do a very good job of caching that stuff (it sucks, actually).

So if your non-singleton scoped classes (or junit tests - like we had ;) contain something like

@Autowired
private MyFud[] myFuds;

Just make a separate singleton object that encapsulates the array/list and wire that into your controller class / junit test instead. Bang you're safe.

Sunday, December 26, 2010

Maven Surefire 2.7.1

Todays release of surefire 2.7.1 is an important milestone for me. Lets start out with what the 2.7 series has to offer

  • Multiple run-orders for tests now supported
    The runOrder attribute lets you specify alphabetical, reversealphabetical, random, hourly (alphabetical on even hours, reverse alphabetical on odd hours) and filesystem. Odd/Even for hourly is determined at the time the of scanning the classpath, meaning it could change during a multi-module build.
  • Faster, smaller
    About 1/3 of the total download size of 2.6. I get quite a lot of feedback saying it's significantly faster too; your mileage will vary.
  • Parallel JUnit
    Surefire is now totally self-contained and no longer uses ConfigurableParallelComputer for anything. Real execution times per test are also reported. It won't get much better than this.
  • Severe memory/resource leak fixed for those of you who have console output.
    The more your tests were writing to stdout/stderr, the worse the problem was. This one has been here since 2.4 ;)
  • Pluggable/Selectable providers
    Surefire is a framework for forking and reporting with a few additional features, such as directory scanning services. Until 2.7, this has all been wired together in one monolithic slab of code with test-providers ( TestNG, junit3/4/4.7) seemingly independent but in reality all welded together by massive dependencies and strange divisions of labor. No more. 2.7.X makes it possible to write your own providers. Best of all there's really not much work you need to do to create one.
    Need a "fork every 20 tests" provider? Fork one of the existing ones and make it yourself on github, probably in less than an hour. This also means we will be closing some of the more exotic requests as won't fix, since you can just do it yourself.
    Read about it here and here for the api
  • JDK 1.3 fork-compatibility restored.
    I ended up doing this just for the sheer heck of it; kind of a challenge. Pardon the language.

There's other issues fixed too, but these are the highlights.

* Why ?
I started programming on my C64 when I was 13 and I've been coding passionately ever since. I went to university and when I finished developing software became my day job. And although I keep my code clean, professional software development is also a lot about making deliveries with trade-offs and sometimes compromises. And we move on. If it doesn't come back to haunt us, it was probably good enough - no matter how frustrated you felt when making it.

Not so with my Open Source work. There I will only do stuff that somehow is the most excellent work I am capable of. It's the hobbyist computing returned, but my capacity is oh so infinitely different from when I was a teenager. Several OSS companies have offered me jobs, which I have turned down. If I was to take that I somehow feel I'd be taking the hobby as work once more.

So how does all of this relate to surefire? Until recently, surefire has been real messy code. While the basic design contains some interesting and pretty sophisticated stuff, it was basically a big mess. Huge classes with 400 line long methods is the trending topic. It was code without any discernible shape or form; mutable state mutating at every opportunity. All this mostly due to different people working on it at different points in time.

I've seen this happen, even with the best of people working together, and I will not dwell further as to the reasons for this. But I love working with the structure of code, and I think programming is communication; me talking to you - disconnected in time and space.

So I refactor. And I think. Sometimes I can think about a change for a week, code it in few hours only to realize it was wrong and throw it all away. Sometimes I can discover midway that there is a more important angle on solving the problem; something totally different is more important and will have bigger impact on future change. And I just stash away everything and do The Thing I Now Know Is Right. Repeat until satisifed.

I spent months of spare time working with surefire 2.7 this way. I think the results are pretty amazing; the plugin is basically transformed into clean code. Every year around Christmas time, I tend to bring this book to the fireplace. It's still one of the most amazing books written about how to think code. Kent has rewritten this book for Java several times, but I still recommend the Smalltalk version - even if you never programmed smalltalk. And take a look at surefire trunk. There's still work to do. Make a patch. Merry xmas.


Friday, February 19, 2010

Concurrency in maven ?

Within the maven community, there has been a push towards parallelizing maven itself
to achieve better build performance within multi-module reactor builds. A number of strategies have been tried, and the main two strategies are: Parallel reactor mode (uses module dependency graph to schedule builds that can be built in concurrently side-by side). The other strategy is known as "weave" mode, and it traverses the modules phase-by-phase instead of module-by module (you can read about it here)

Both have "fully" functional implementations available, and weave mode is quite a lot faster than parallel mode. The code is available at http://github.com/krosenvold/maven3. Just build and run with -Dmaven.threads.experimental=4

So what is this post about ? I am the primary author of "weave" mode, and for the last weeks I've been searching for an elusive goal: 1000 consecutive green builds of 1 single project on my CI environment.

Initially I was quite afraid of the thread safety issues withing maven; after all retromounting concurrency to any non-concurrent code can be a daunting task. Fortunately there is a lot of state that is /copied/ in maven reactor mode. From a concurrency perspective, this saves the day.

So why am I not getting my 1000 greens ? Every 3-400 builds it would fail, with strange errors. I asked a few questions (and this one) on stackoverflow.com. It's the file system. The java file system
has no guarantees of /anything/ when it comes to concurrency. The only thing you can be sure about is that the single thread that wrote the file can also read it afterwards.

javac uses the file system. And I was quite baffled by this; in weave mode the javacs are invoked on a pretty tight schedule; they typically come within just a few ms of each other. Every now and then the downstream javac would complain about "bad class files" from the upstream javac. But the scheduling is done properly, and the first javac /was/ done. How to solve it ? Turn on "forkMode" in maven for javac.

I had a chat with the nice folks at #kernel and they told me that all contents of a file should be concurrently visible to /everyone/ upon close() in a modern linux kernel. When I turned on forkMode in javac the problem went away. Because forkMode=true basically delegates the visibility issues to the os.

You /can/ try this yourself if you check out from github and try to build a project. It works best if you do a "mvn -Dmaven.threads.experimental=4 clean install", since that'll write a lot of files.

I'm still scratching my head about what to do with this; given that forking delegates visibility to the underlying os one could just fork everything all the time. Or find some other option.. Suggestions ?

Thursday, January 14, 2010

Run your junit tests concurrently with maven, junit (and maybe also spring3) in 5 minutes or less!

Surefire 2.5 is released, and it contains the concurrent junit patches. In this post I'll give the quick rundown of how to try out your current maven based build in a concurrent fashion. Just a few initial thoughts:

Will my tests run concurrently ?


Probably not, as is. Most existing test fixtures that people use have singletons and shared state that needs to be fixed first. This may be everything from a shared file, shared TCP/IP port or a static member variable in some base class that can't be static any more.

It took me about a day to fix these things in my current project. My project is large and complex. using all sorts of dark spring magics. Your mileage may vary.

What performance gain can I expect ?


For an IO-bound test (integration test/selenium test etc), the sky's the limit ;)

For a fairly optimized unit-test set, expect little or no gain - maybe 15-20%.
The reason for this is that until jdk7, all classloading and all classpath bound resource access is synchronized across the VM. Running unit tests is mostly about classloading and classpath resources :( If your unit-tests have other kinds of I/O bindings you may be luckier.

If you're using spring inside your test fixtures (like we do), you can probably squeeze a few drops of speed out of it by making lazy-init==true globally. You're going to test it all anyway, right ?

How to do it!


Make sure you upgrade to surefire-2.5:


<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
</plugin>


Make sure you upgrade to junit 4.8.1 (still not in maven central repo, install locally):

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.1</version>
<scope>test</scope>
</dependency>


(You /can/ use 4.7 but it still has a couple of concurrency bugs in it that were fixed in 4.8.1)

Fix your surefire configuration:

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
....
<parallel>classes</parallel>
</configuration>
</plugin>


Legal values for parallel are "classes, methods or both". Now you can run, but you should probably read the rest of this post first...

Classes, methods or both ?


From a concurrency perspective, "classes" is probably the easiest to start with, since it will probably run into the smallest number of troubles in your test fixtures. I really recommend you try to get both working, since you'll probably need to identify any additional issues raised by using "methods". You want a test-suite you can trust, right ?

The fine print


One drawback of the current default concurrency implementation in junit is that it does not allow you to constrain threads, which is desirable for almost all use cases I am aware of. But junit is extendable, and I have made a supplemental add-on that allows threads to be configured too. Surefire knows to invoke this one if it's present on your classpath, meaning you'll get additional options available:

The configurable-parallel-computer still has a few issues that are unsolved, so you
may consider dropping by the issue tracker to check if these will bother you before adding it to your project

git clone http://github.com/krosenvold/configurable-parallel-computer.git
cd configurable-parallel-computer
mvn install


<dependency>
<groupId>org.jdogma.junit</groupId>
<artifactId>configurable-parallel-computer</artifactId>
<version>1.5</version>
<scope>test</scope>
</dependency>




<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
....
<parallel>classes</parallel>
<threadCount>2</threadCount>
</configuration>
</plugin>


You can also use the setting "perCoreThreadCount", which scales threadcount per CPU core.

The configurable-parallel-computer project also contains a better output demultiplexer than the one in surefire (which has a ketchup-bottle behaviour). Surefire knows about this one too, so adding configurable-parallel-computer to your classpath will give you smooth project output. I'm sure we'll get the improved version into surefire at some later time.


Spring


If you're using spring you need to use a forked version of spring-test. The patch I submitted to spring is targeted for 3.1, whatever that may mean in practice:

git clone http://github.com/krosenvold/org.springframework.test.git
cd org.springframework.test
mvn install

You need to replace your dependency on "spring-test" to the forked version:


<dependency>
<groupId>org.rosenvold.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>3.0.0.RELEASE</version>
<scope>test</scope>
</dependency>

Remember to also suppress the transitively dependent spring-test artifacts, like this:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>3.0.0.RELEASE</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</exclusion>
</exclusions>
</dependency>


Make sure mvn dependency:tree does not contain the spring version of spring-test. Any inclusion of the 3.0 artifact WILL get you into trouble.

If you're using a Mock Session Scope based on the Spring Session Scope (with a custom ContextLoader), you need to make sure you override the synchronized methods in the base class with your own implementations, or your tests may deadlock on the session scope. This is a real bug in spring, but one that probably does not occur to often in real-life scenarios; but quite a lot when running concurrent tests.

Off you go !

Monday, October 5, 2009

Concurrent junit with maven and spring3 updated for RC1

To celebrate the release of spring rc1, I have updated the patches and the procedure for building custom versions of junit, surefire and spring3. Spring had about 500 commits since I created the initial patchset, and they were no longer applying cleanly.

The instructions in my original blogpost now reflect the revised procedure, and in about 20 minutes you can have it all up & running.


The original instructions can be found here.

Memo to self: How to patch an open source CVS/SVN project with GIT

Most CVS/SVN open source projects will prefer patches to be submitted as follows:

1. First patch contains a failing test
2. Second patch contains bugfix/improvement and possibly additional testcases and maybe also changes to the initial failing test case

The smart way to do this with git is as follows:

1. Clone project, if it's a SVN project use github's git-svn import (*much* perferred to using git svn clone yourself)
2. Create an initial feature branch masterForGit, where you add stuff that is nice for working this project in a git environment; typically a .gitignore file and any local scripts you need to be able to work with the project. Make sure this project compiles well and does not add unwanted files to git before proceeding (git does not handle empty directories same way as svn so you may need to correct this in this branch)
3. Create a feature branch failingTest based on masterForGit. In this branch you create the original failing
test what will be submitted as proof.
4. Create a feature branch bugFix that is branched off failingTest. In this branch you fix the bug and add any subsequent test cases.
5. When you're all done, you typically do diff between failingTest and masterForGit to get the patch file for "proof" bug. Then you diff bugFix and failingTest to get fix-patch. Since you created the "masterForGit" branch initially, none of the patches get polluted with temp-stuff you did locally.

And, if you end up maintaining this patchset, you can just update from svn through github and merge through all of your branches. Easy.

Thursday, October 1, 2009

Status of concurrency patches

AspectJ 1.6.6 is released and contains the patch I submitted there. 1 patch down.

The main patch for spring is scheduled for release 3.1. The patch no longer applies cleanly, but I will be updating it fairly soon, probably some time over the weekend. I may also try to publish a forked org.springframework.test to some maven repo by the time 3.0 goes release.

Surefire is another story. I am not sure anyone is actively maintaining this plugin any more. Anyone know any committers ? I have been considering forking the surefire plugin permanently and remove cruft, it sure has a lot of it.

As for the patches to junit itself they are submitted but still not accepted. There may be possible workarounds for this that I'll can consider when I revise the patches.

Sunday, July 5, 2009

Are four cores required to surpass one ?

My recent post about running unit tests in parallel has led to some interesting food for thought:

When running regular unit tests, running with 2 cores seems to be no faster than one core. 4 cores (and arguably a newer CPU architecture) had a significant impact, where performance nearly doubled. The hyperthreaded quad-core i7 920 was *slower* than a 3Ghz core 2 duo when running single threaded, but nearly twice as fast in a multithreaded scenario. What's happening ?

I looked into the issue with jprofiler, but there is no obvious lock contention or other clearly visible bottleneck. The only explanation I can think of so far is this:

The test I was running was extremely simplistic, and there was no real cpu requirement in running the test methods. So the overhead of creating thread pools and all that actually amounts to just as much computation as running the tests. Likely ?

After my summer vacation, I will try to find out. I probably need to run with more realistic test cases. I figured I'd build surefire with threads, because thats a fairly heavy build. In the mean time, your thoughts are welcome.

From legoland,

Kristian

Wednesday, July 1, 2009

Run your junit tests in parallel (with spring 3.0 and maven)

Swimming in a sea of patches...



Note; Most of the content in this post has been surpassed by a newer entry.

If you're willing to apply a few patches, you can now run your junit tests in parallel. There are two main use-cases for this; one is to make your regular unit tests run faster, the other is for io-bound tests, where you want to run several in parallel because you're waiting for external systems.

Just to whet your appetite, here are some numbers from a testcase (running 1000 instances of a simple unit-test-class):

Legend:
SC = SingleThreadedComputer (Computer, Junit47-snapshot class)
PC = ParallelComputer (ParallelComputer, Junit4.7-snapshot class)
CPC = ConfigurableParallelComputer (My project, see references)
C=Classes (one thread per class)
M=Methods (one thread per method)






































Core 2 duo 3.14GhzIntel i7 920
SC203451
PC(Classes, Method, Unlimited threads)406806
CPC(Methods,16 threads)218214
CPC(Classes, Unlimited threads)203116
CPC(Classes,Methods, Unlimited threads)266147

Running time in ms, 1000 simple tests

The table shows that for most dual-core solutions, running with parallel threads is currently never any faster than running non-threaded. Switching to the brand-new Intel i7 (4 hyperthreaded cores) has a marked effect, where simple unit test performance is doubled.

The lack of punch does, of course, change the moment your tests start doing IO (Integration tests, selenium tests and other web-tests).



The juicy stuff
svn co https://svn.openqa.org/svn/selenium-rc

Second build with mvn clean install: 102 seconds.
With 80 threads class-parallel on the i7: 37 seconds.

Class-parallel works easily on most tests.

A sea of patches


Getting all of this to work was not without its problems, though. To get this running, I had to patch just about half the libraries in use in my current stack. Furthermore, there's a huge difference between getting it to run and getting it to run without hiccups - every time. These patches insure that your infrastructure works as it should, but are your tests concurrent ?

Patches involved


See below for how to apply these patches in a simple manner.
Spring (3.0 trunk):
http://jira.springframework.org/browse/SPR-5863
AspectJ: Patch trunk with this patch (if using spring) (This patch is included in version 1.6.6)
https://bugs.eclipse.org/bugs/show_bug.cgi?id=281654
Junit4.7:
Several patches needed for thread safety:
http://github.com/KentBeck/junit/issues#issue/16
http://github.com/KentBeck/junit/issues#issue/18
Maven: You need a patched version of surefire that supports junit 4.7:
http://jira.codehaus.org/browse/SUREFIRE-555
You'll also probably want to be using the ConfigurableParallelComputer instead of the ParallelComputer that's included with JUnit.
git://github.com/krosenvold/configurable-parallel-computer.git

With these patches in place you're smooth sailing ;)

Applying the patches


Note: If you did this on the pre rc1 version of this patchset, I recommend that you start from a fresh copy of everything this time.
If you're using maven you could try this sequence:

git clone git://github.com/krosenvold/spring-framework-concurrent-junit-patch.git
git clone git://github.com/krosenvold/junit.git
git clone git://github.com/krosenvold/configurable-parallel-computer.git
git clone git://github.com/krosenvold/spring-test.git
git clone git://github.com/krosenvold/spring-concurrency-test.git
cd junit
ant
cd ../spring-framework-concurrent-junit-patch
./installJunit
cd ../spring-test
mvn install
cd ../configurable-parallel-computer
mvn install
cd ../spring-framework-concurrent-junit-patch
./checkoutSurefire
./buildSureFire
./applySureFirePatch
./buildSureFire




cd ../spring-concurrency-test
mvn install # Test project to verify that everything is ok


Your new versions


JUnit should be modified to 4.7-CONCURRENT
spring-test should have version number 3.0.0.RC1-CONCURRENT
Surefire should be modified to 2.5-SNAPSHOT
You must update your aspectj version to 1.6.6 in your project. Spring does a transitive
include on 1.6.5

You can see the version number for the spring artifacts when building spring. Probably something like 3.0.0.BUILD-20091005102426

Maven surefire settings



<plugin>
<artifactid>maven-surefire-plugin</artifactid>
<version>2.5-SNAPSHOT</version>
<configuration>
<parallel>classes</parallel>
<useUnlimitedThreads>true</useUnlimitedThreads>
<threadCount>80</threadCount>
<perCoreThreadCount>true</perCoreThreadCount>
</configuration>
</plugin>


UnlimitedThreads knocks out threadCount and perCoreThreadCount.

Look at the various "install" scripts to see the version numbers of the artifacts.
Simple, eh ?

And while we're at it: Half of the work with patching these projects has been about fighting with version control systems and custom made build scripts. So please; switch to GIT and maven: I can build any maven project without reading as much as a readme file. Maven allows me as a casual bystander to *easily* make contributions; I never need to read that 4 page "how to build" manual! Git is the only version control tool that respects my right/duty to patch, change and upgrade other projects. It allows me to do all these things without having to *ask* anyone. Repeat after me: Git and maven encourages free collaboration; a key idea of open source, right ?

http://twitter.com/krosenvold

Thursday, October 9, 2008

Using ajax transaction counts in selenium tests

Sometimes your "only hope" in making a selenium web test stable is to keep track of the number of ajax requests that have happened on the client side.

An example of this is the ajax request that normally returns exactly the same html as was present in the dom before the request. Although this may sound stupid, there are legitimate situations for this.

My test would look like this:

int transactionNumer = selenium.getCurrentAjaxTransactionNumber();
selenium.clickLink("SomeLink");
selenium.waitForAjaxTransactionNumberChange(transactionNumer);
-- rest of test ---


This test is free from timing issues, because it will not proceed to the rest of the test before the ajax request is completed.


public int getCurentAjaxTransactionNumber() {
String eval = selenium.getEval("window.ajaxRequestNumber");
return Integer.parseInt( eval);
}





In my ajax.js file, which wraps prototype, I will typically include two lines like this:

window.ajaxRequestNumber = 0;


Now you will have to find a way to patch into your ajax framework to update this value. For prototype, this would work:


Ajax.Responders.register({
onComplete: function() {
window.ajaxRequestNumber++;
}
});


Now you can track request numbers, and yes - they start with value 0 on page load.

Wednesday, June 11, 2008

Detecting javascript errors with selenium

I've only found out how to do this by including a few javascript functions that get included in the code. I have made no attempt to remove this from production code:


window.onerror = function(){
if (sessionStorage){ // Mozilla only
var cnt;
if (sessionStorage.errcnt){
cnt = parseInt(sessionStorage.errcnt);
} else {
cnt = 0;
}
cnt++;
sessionStorage.errcnt = cnt;
}
return false;
}

function hadJavaScriptError(){
if (sessionStorage){ // Mozilla only
if (sessionStorage.errcnt){
delete sessionStorage.errcnt;
return true;
}
}
return false;
}
Somewhere in your selenium test you can put this check:
String hadJserror = getSelenium().getEval("window.hadJavaScriptError()");
assertFalse("Page had a javascript error, this error has occured somewhere during the test.", Boolean.parseBoolean(hadJserror));


I've put this straight after a common waitForPageToLoad function that we are using, please note that if you do so, it must be after the call to waitForPageToLoad.

Note that the javascript code uses mozilla session store (and probably IE8) to actually keep a persistent count of javascript errors. I'm sure some "userData" for IE could be used for older IE versions