The point is missed

Museum of public mistakes and unfinished projects

Phasing over from java to scala pt. 3 – What about the tests?

with 2 comments

I’ve now spent some time every now and then converting Java-classes into Scala classes. I’m one of those Agile loudmouths so some of you may wonder what I’m doing about the tests. I mentioned that all tests pass in pt. 2 but I have not written about how I test. Well, it probably comes as no surprise that the current code is tested in JUnit and I have simply kept my old test-suite intact when phasing over. This strategy works well since what I’m really doing is refactoring. I move class by class in baby steps, running my tests after each change to make sure that everything is still working as it should. But I’m starting to be done with the move now and a strategy for writing new scala-code seems more and more relevant.

What does Buildr support?

Since I’m building with Buildr I would need a really good reason to go with something that Buildr can’t handle. Let’s have a look at what our options are:

Buildr supports three Scala testing frameworks: ScalaTest, ScalaCheck and Specs. Scala testing is automatically enabled if you have any .scala source files under src/test/scala.

Ok, ScalaTest, ScalaCheck and Specs in any combination. Choices, choices… After looking around in the documentation from all three frameworks I found the following:

  • Scala Check is a scala variant of QuickCheck for Haskell. Scala Check is supported by both ScalaTest and Specs
  • ScalaTest seems to me to be a rather traditional xUnit-style testing-framework. There are a few unusual constructs such as the FunSuite that uses functions instead of test-prefixed method-names to identify tests but in general ScalaTest feels like familiar territory with a few exotic flowers around.
  • Specs is similar to rspec for Ruby and claims to be a BDD framework.

Both specs and Scala Test have JUnit-support which allows me to run my tests from JUnit. While this may not seem like a big deal at first it does give tremendous value when working with mixed code like I do, I can run all my tests/specs using the same JUnit-tool, this limits task switching and frankly improves the likeliness that I will run my tests/specs as frequently as I should.

Scala Check seems interesting to me since I have been playing witht JUnit 4.4 theories. I’m glad it’s available in both frameworks so that my choice is not limited by that aspect.

I think I will take specs for a spin since I am a fan of rspec and BDD, I’m also curious how an rspec inspired tool would look in scala, it’s bound to do things that can’t be done in java. So more for me to learn that way seems to be the verdict.

Ok,

Through UGDD I have come to the conclusion that I need to add some features to the SiteGraph. I need to represent directories as nodes in the graph.

Installing specs

If you’re a Maven user, you need to add the following dependency to your pom file:

    <dependency>
      <groupId>org.specs</groupId>
      <artifactId>specs</artifactId>
      <version>1.3.0</version> <!-- specify the version here ->
    </dependency>

In buildrish this translates to

SPECS = group("specs", :under=>"org.specs" :version=>"1.3.1")

It turns out that we also have to add the scala tools repository to our buildfile. I did not find that information on the site, perhaps this is already done in maven or it’s so obvious that everyone that worked more than 2 days with scala is aware of that. This is how you add the repository to you buildfile:

repositories.remote << "http://www.agical.com/maven2/"
                    << "http://www.ibiblio.org/maven2/"
                    << "http://repo1.maven.org/maven2/"
                    << "http://scala-tools.org/repo-releases"

In order to run compile and run with specs we also need to add the following two lines to our buildfile in our scala-project:

test.compile.with SPECS
test.with SPECS

Ok, we’re all set… let’s write the first spec. Buildr dictates that we should put our specs in src/test/scala and name them according to the <SpecName>Spec.scala pattern.

Said and done, behold the first specification:

package com.agical.publisher.content.site
import org.specs._

object PublishSiteGraphSpec extends Specification {
  "directories are nodes" in {}
}

And now run it with buildr:

Testing publisher:scala-core
Compiling publisher:scala-core:test into /home/jocke/dev/publisher/scala-core/target/test/classes
Running tests in publisher:scala-core
Running java com.agical.publisher.content.site.PublishSiteGraphSpec
Specification "PublishSiteGraphSpec"
  specifies
  + directories are nodes

Ok, I don’t know about you but switching between a command window and eclipse annoys me. Let’s see what I can do about that…

Running via JUnit from eclipse

Lets see how well the promised JUnit integration actually works. It turns out that the JUnit support is all but satisfying :(

It starts ok:

package com.agical.publisher.content.site
import org.specs._
import org.specs.runner._

class PublishSiteGraphSpecTest extends JUnit4(PublishSiteGraphSpec)
object PublishSiteGraphSpec extends Specification {
  "directories are nodes" in {}
}

All I have to do is to add a class that extends JUnit4. I don’t find this much more annoying than having to add the @Runwith(Theories) annotation in JUnit4 when testing with theories.

Now to the ugly part:In order to be able to select your JUnit4 classes, you need to add the output directory of your project to your build path:

  1. Select your project
  2. Go to “Build Path / Configure Build Path”
  3. In the “Libraries” tab, “Add Class Folder”
  4. In the “Class Folder Selection” dialog, do “Create New Folder”
  5. In the “New Folder” dialog, select “Advanced” and “Link to folder in the file system”
  6. Select the output folder of your project
  7. Refresh your project (F5 on the project’s folder)

You should now be able to select the JUnit4 classes of your Scala project.

Quite a turnoff but…

It works!

It works!

It works!!!

But when I try to run builder again the following error greets me:

Compiling publisher:scala-core:test into /home/jocke/dev/publisher/scala-core/target/test/classes
NoClassDefFoundError: junit/framework/Test
rake aborted!
junit/framework/Test

Obviously I have forgotten to put JUnit on the test-classpath. Said and done:

test.compile.with [JUNIT4, SPECS]
test.with [JUNIT4, SPECS, LOGBACK]

But the error is still there!!! This is kind of bad, people have enough resistance to automatic specification and tests as it is, getting them to run should be easy!

Ok, I am curious, what is going on here? Running Buildr with –trace gives the following extra information:

** Execute publisher:scala-core:test:setup
** Execute publisher:scala-core:test
NoClassDefFoundError: junit/framework/Test
** Invoke publisher:scala-core:test:teardown (first_time)
** Execute publisher:scala-core:test:teardown
rake aborted!
junit/framework/Test
/var/lib/gems/1.8/gems/buildr-1.3.2/lib/buildr/java/test_frameworks.rb:68:in `method_missing'
/var/lib/gems/1.8/gems/buildr-1.3.2/lib/buildr/java/test_frameworks.rb:68:in `filter_classes'
/var/lib/gems/1.8/gems/buildr-1.3.2/lib/buildr/java/test_frameworks.rb:363:in `tests'
/var/lib/gems/1.8/gems/buildr-1.3.2/lib/buildr/core/test.rb:423:in `run_tests'
/var/lib/gems/1.8/gems/buildr-1.3.2/lib/buildr/core/test.rb:196:in `initialize'

Ok, not that it tells me a lot but I bet that peeking into test_frameworks.rb will. It does not show in this blog but days have passed and I have considered jst going with scala-test instead or possibly the combination of specs and scala-test but I stubbornly refuse to give up even though I should. I tell myself that I might learn a thing or two about Buildr.

After getting my hands dirty I find the following on line 308:

      # ScalaTest dependencies
      DEPENDS = ["org.scalatest:scalatest:jar:#{VERSION}"] +
                 JMock::REQUIRES +
                 ScalaSpecs::REQUIRES +
                 ScalaCheck::REQUIRES

A simple

+  JUnit::REQUIRES

Solves the issue:

Running tests in publisher:scala-core
Running java com.agical.publisher.content.site.PublishSiteGraphSpec
Specification "PublishSiteGraphSpec"
  specifies
  + directories are nodes
Total for specification "PublishSiteGraphSpec":
Finished in 0 second, 72 ms
1 example, 0 assertion, 0 failure, 0 error

And I can go on to make the specification fail.

Up until this part phasing over to Scala has been a smooth ride. Specs offered some ugly hack to make it work in eclipse,but it woks. Buildr gave me a really hard time and I spent hours literally before I decided it was time to patch Buildr itself. Buildr has on the other hand been a very friendly companion up until this time and I assume that the combination Buildr, Scala, Specs + JUnit has been that common so far. On the other hand, if this was ant or maven I would have had a much harder time patching the tool. It makes a certain kind of sense to build with a dynamic language, to me anyway.

In the next part we will make our specification fail.

Also, I have learned how easy it is to be on the bleeding edge with buildr and share it here

I found implicits worth it’s own little entry here

About these ads

Written by johlrogge

September 10, 2008 at 9:44 pm

Posted in Uncategorized

Tagged with , , , ,

2 Responses

Subscribe to comments with RSS.

  1. [...] the latest and greatest Posted in Uncategorized by johlrogge on September 13th, 2008 In a previous post I ran into some problems with Buildr’s support for Specs in combination with JUnit. I googled [...]

  2. [...] you’re note tired of my ramblings yet the next part is here. Possibly related posts: (automatically generated)Buildr – Keeping up with the latest and [...]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: