Thursday, January 31, 2008

Which Style Is More Readable?

I've been writing ScalaTest tests for the ScalaTest TestNG integration (say that five times fast). I used a couple of different styles and I was hoping to get some input on which style people thought was more readable, more clear. Both styles are functional, one merely masks it a bit while the other flaunts it.

The first style I'll show is the discrete style. Here I call a test method which takes a function and executes it.


test( "Reporter Should Be Notified When Test Passes" ){

val testReporter = new TestReporter

// when
new SuccessTestNGSuite().runTestNG(testReporter)

// then
assert( testReporter.successCount === 1 )
}


test( "Reporter Should Be Notified When Test Fails" ){

val testReporter = new TestReporter

// when
new FailureTestNGSuite().runTestNG(testReporter)

// then
assert( testReporter.failureCount === 1 )
}


The I'm showing only two examples of calling the test function but in actuality I have many more tests. Notice that in each test the first line is always the same:


val testReporter = new TestReporter


There are benefits to this. All the code is right there and you can read the test method without looking anywhere else. There are also some negatives as well. I have the same line of code in several places.

Now I'll show the even more functional style. It takes a little more explaining. Here I declare a withFixture method that accepts a function that takes a TestReporter as its input. The withFixture method creates the TestReporter (so each test call doesn't have to) and calls the input function passing it the TestReporter. To create tests I call the testWithFixture function which takes a function and passes it to the withFixture function I just wrote.


override def withFixture(f: (TestReporter) => Unit): Unit = {
f(new TestReporter)
}


testWithFixture( "Reporter Should Be Notified When Test Passes" ){
t: TestReporter =>

// when
new SuccessTestNGSuite().runTestNG(t)
// then
assertThat( t.successCount, is(1) )
}


testWithFixture( "Reporter Should Be Notified When Test Fails" ){
t: TestReporter =>

// when
new FailureTestNGSuite().runTestNG(t)
// then
assert( t.failureCount === 1 )
}



I'm realizing as I'm writing this that all the extra explaining I had to do is because the code is more complicated. There are definite negatives here. Code is being passed around to other code, you might now be sure how things are actually running, you might not be sure where the TestReporter object is coming from. On the upside the methods are slightly shorter and I've removed the most obvious duplication by moving it to the withFixture function. There's still plenty of duplication (in each example) that could be removed but you can definitely push duplication removal too far. Especially in tests, you must balance duplication and indirection. They are in direct opposition.

Does this code push it too far?

Is this just a setup method in disguise? I'm of the opinion that setup methods are bad, but at least here everything is immutable.

If people were to get used to this style would it become more readable in the long run?

Please please let me know your thoughts.

Wednesday, January 23, 2008

Scala and TestNG in Far Greater Detail

I wrote before on running TestNG in Scala and due to popular demand I'm going to go into much greater detail. My goal is to show that running TestNG in Scala is as easy as it is in Java. I've thrown in Hamcrest to show that that integrates seamlessly as well. Hopefully along the way you'll learn a couple of Scala nuggets too. And, be warned I'm assuming you know a bit about TestNG so I'm not going to explain it much. If you don't...www.testng.org

I created a new Scala class for testing my AndGate class. The idea is that I want to make sure that my AndGate is on or off according to the standard And boolean logic table:

x y | output
------------
0 0 | 0
0 1 | 0
1 0 | 0
1 1 | 1

The testing class is called ScalaTestNGExampleTest, and it looks like this:


import org.testng.annotations._
import org.hamcrest.MatcherAssert._
import org.hamcrest.Matchers._;
import org.testng.annotations.DataProvider;
import com.joshcough.cpu.gates._

class ScalaTestNGExample {

@DataProvider{val name="generators"}
def createGenerators = {
val gens = Array(off, on)
for( x <- gens; y <- gens ) yield Array(x,y)
}

private def on = new Generator(true)
private def off = new Generator(false)


@Test{ val dataProvider="generators" }
def testAndGateStates(genA: Generator, genB: Generator){
val and: AndGate = new AndGate(genA, genB);
val whatItShouldBe = genA.on && genB.on
assertThat( and.on, is(whatItShouldBe) );
println( and.on + "==" + genA.on + "&&" + genB.on )
}

@BeforeMethod def printLineBefore = println("------entering test------")
@AfterMethod def printLineAfter = println("------exiting test------")

}

If you aren't familiar with Scala that might look a bit like magic, so I'll explain one step at a time.

Data Provider

The first thing I did was set up a data provider for my logic table:

  1. The annotation declaration is obviously different than in Java. Instead of parentheses, you have to use curly brackets. Instead of simply name/value pairs, you have to declare vars. I could explain why, but instead you could just go to http://www.scala-lang.org/intro/annotations.html.

  2. DataProvider methods are supposed to return Object[][], but...what the heck is this one returning? Well, before I explain what that funky for statement is actually doing I'll just announce that this method is actually returning Array[Array[Generator]]. I could have made it more explicit by saying def createGenerators(): Array[Array[Generator]] but Scala's type inference lets me get away with leaving it off. Does leaving it off hamper readability? In most leaving it off is just eliminating some redundancy. Maybe in this case I should have left it on, but I wanted to show type inference a little bit.

  3. Wait a second...Array[Array[Generator]] isn't Object[][]...or is it? Actually, yes. Scala's typed array class (Array[T]) actually compiles down to Java arrays. In this case, Array[Array[Generator]] compiles down to Generator[][] in Java.

  4. What is Array(on, off)? The type of Array(on, off) is Array[Generator] and it contains two elements, Generator(true) and Generator(false) which are returned from the on and off methods respectively. It may be confusing for a Java programmer to see simply "on" with no parens. In most cases (for reasons far beyond the scope of this post) Scala doesn't force you to use parens on method calls with no arguments.

  5. Ok finally, what is that funky for loop looking thing doing? Rather than explain, why don't I just give the equivalent code in Java for the createGenerators method?


public Generator[][] createGenerators() {

Generator[] onAndOff = new Generator[]{ on(), off() };

Generator[][] gensToReturn = new Generator[4][2];
for( int i = 0; i<onAndOff.length; i++ ){
for( int j = 0; i<onAndOff.length; j++ ){
gensToReturn[i+j] = new Generator[]{ onAndOff[i], onAndOff[j] };
}
}
return gensToReturn;
}

Honestly? Those three lines of code are doing all of that...? Yes. Honestly. Rather than me trying to explain it though, James Iry does an excellent job in part 2 of his four part series on monads called Monads are Elephants. That is the link to part two, but I recommend reading all four.

So now we have a data provider and we have a reasonable idea how it works. But quickly before I move on, heres another way I could have done it which is arguably more readable but not nearly as much fun. Once again, the idea here is that this data provider is essentially creating the And logic table for us.


def createGenerators = {
Array(Array(on, on),Array(on, off),Array(off, on),Array(off, off))
}

Test Method

At this point I think everything else is really straight forward. Despite that, I'll go over the test method in detail.
  1. The @Test annotation is defined in the same fashion as I described above for @DataProvider. In this case I define which data provider to use. Done.

  2. The method takes two Generator parameters which come from createGenerators method.

  3. The first line simply instantiates an AndGate object using the two Generator parameters.

  4. The second and third lines simply assert that the AndGate is what it should be! It should be on only when both generators are on, according to the logic table. The third line uses Hamcrest matchers for asserting. I'm not going to bother explaining them here.

  5. Finally I throw in a print statement.


BeforeMethod And AfterMethod Annotations

Before each test method is called, TestNG will call any methods annotated with @BeforeMethod. In my case before each method I just print a nice message. The same goes for @AfterMethod, but after each test method, of course.

Results

Here is my output from the console:

[testng] -----------entering test-----------
[testng] true==true&&true
[testng] -----------exiting test-----------
[testng] -----------entering test-----------
[testng] false==true&&false
[testng] -----------exiting test-----------
[testng] -----------entering test-----------
[testng] false==false&&true
[testng] -----------exiting test-----------
[testng] -----------entering test-----------
[testng] false==false&&false
[testng] -----------exiting test-----------

Problems

I did run into a few problems.

  1. FIXED: Unfortunately, I couldn't use @Test{expectedExceptions = {SomeException.class}} because Scala doesn't you say Anything.class.
  2. Running the tests through Eclipse is not as easy as it is in Java, and needs some work. I ended up mostly running through Ant, but sometimes through Eclipse.

Conclusion

I hope I've convinced you that running TestNG in Scala is simple. I didn't test all the features, but most of what I have tested works great. I plan to use it for most of my Scala development. I personally think its pretty far ahead of the pack, but if you want to see for yourself they are: ScalaTest, ScUnit, Rehersal, JUnit, and specs. I've tried the last four, and of those I thought specs was really nice. It seems like a reasonable alternative.

I am very open to hear ideas on why I should switch to an xUnit test framework built in Scala. Are there any advantages? What are they?

Sunday, January 20, 2008

My Small Problem with the Scala Actor Model

Something seems wrong to with the whole send/! idea. The Scala guys say ! apparently means "send", but it really means "add message to actors mailbox", or "put". Take this example:

actor ! message
actor send message

If ! means "send", then it certainly seems like the actor is sending the message. Of course, you have no idea who its sending it to, so by that logic it must be getting the message, but it still just seems confusing. I think the API might be more readable if it used one of the following:

actor <-- message
message --> actor

I've demonstrated that you can use --> and <-- as method names already, so, why not use them here?

Scala: Fold Left Question

I recently realized that I could make a piece of code I posted in a recent blog much cleaner using foldLeft. I have a bit of a problem however, the code is in a very performance sensitive area and I should break out of the fold whenever I encounter a certain condition. To the best of my knowledge foldLeft has no way to break out. It just folds all the way and you get your result at the finish. This is a bit unfortunate. Is there a way to break out and still keep the code clean?

Here is my example, old code first. A PowerSource is on if any of its incoming power sources are on.


private def updateOnOff = {
def calculateOnOff: boolean = {
incomingPowerSources.foreach( p => {if( p.isOn ) return true; })
return false;
}
val newOnOff = calculateOnOff
if( cachedOnOffBoolean != newOnOff ){
cachedOnOffBoolean = newOnOff
notifyConnections;
}
}


Here is the new code using foldLeft.


private def updateOnOff = {
val newOnOff = incomingPowerSources.foldLeft( false )(_||_.isOn);
if( cachedOnOffBoolean != newOnOff ){
cachedOnOffBoolean = newOnOff
notifyConnections;
}
}


The new code is far nicer than the old code. I've decided I'm going to go with it. In most cases PowerSources have only one direct input. Some have two, like OrGate, but for now I'm going to see what kind of performance hit I get.

Now, if only I had a performance testing framework in Scala. Does anyone know of one?