Max Blog

My Blog

From Test to Story, from Methods to Scenarios

As we discussed earlier tests shows how the program under test should work.
JUnit test can be understood by people having some Java background. But what’s about people on your team that have no programming background but still are interested in the way the program work or even want to contribute there own expectations.

Those problems are addressed by Behavior Driven Development (BDD).
There are dozen of frameworks for BDD and they all trying to make testing more readable. In my opinion BDD Tests also improves structure of the testing itself.

The framework can be divided in two categories. One that use internal DSL and others that use external DSL. (for a few months I wrote a short post on internal DSL in ActionScript)
In my opinion the problem with internal DSL approach is that you can mix the code inside your scenario declaration and this is not a structural improvement.
When you use an external DSL for testing you have to structure your code and the copy&paste amount of source code keeps to the minimum. If you have another scenario that is pretty similar to one you already wrote you just copy the scenario and changes the parameter. You don’t have to write or duplicate any line of code.

My BDD framework of choice for MockitoViz is JBehave. It’s external DSL based and has a clear structure.

It has three main keywords for Scenario description: Given, When, Then.

If you think about how a test is structured, you see that for a test you have to create a state where the unit under test will be used. It could be the instantiation of the class you would like to test, or creation of the input if it is a complex one.

The creation of the state should be described under the keyword Given.

Given a Compilation Unit from this source code:
package foo;
public class A {
  public void bar(){
    A a = mock(A.class)
  }
} 
And a visitor to FindMockedObjects with stubbed BindingHandler
And stubbed BindingHandler witch returns 'A' as type

The And keyword can be used so you don’t have to write Given every time.

After that you want to fire up an action that will give you some output you wan’t to test. In other word’s you want to use your program under test.

This should be described under the keyword When

When the visitor have visited the AST

Now we can write done our expectations leaded with the keyword Then

Then found mocks should not be empty
And 1 mock should be found
And mocks name should be 'a' 
And mocks type should be 'A'
posted by admin in to Test or not to Test and have No Comments

Mock to visit

Let’s write some actual code that we will use for visualization.

To visualize mocked object we should collect the creation of the mocks in the class or method you are interested in.
So we need to evaluate the code to find method calls that creates mocks in Mockito framework.
The simplest way to evaluate AST is to create an ASTVisitor. AST parser will generate the AST from code but it is not the only thing that it normally does. It also binds symbols to declarations. The problem with that is that the AST parser have to be in position to look up all declarations and this is a problem if you just want to provide a snippet of code.

So any way, here is the test class for visitor witch should find creations of mocked objects.

public class TestFindMockedObjects {
 
	private Block ast;
	private BindingHandler bindingHandler;
	private List<MockedObject> foundMocks;
 
	@Test
	public void canFindMock() throws Exception {
		String javaCode = "A a = mock(A.class);";
		setup(javaCode);
		when(bindingHandler.getTypeName(Matchers.any(Type.class))).thenReturn("A");
		findMocks();
		assertThat(foundMocks.isEmpty(), is(false));
	}
 
	@Test
	public void canFindMockWithProperName() throws Exception {
		String javaCode = "A a = mock(A.class);";
		setup(javaCode);
		when(bindingHandler.getTypeName(any(Type.class))).thenReturn("A");
		findMocks();
		assertThat(foundMocks.get(0).getObjectName(), is("a"));
		assertThat(foundMocks.get(0).getTypeName(), is("A"));
	}
 
	@Test
	public void canFindMockInAssignment() throws Exception {
		String javaCode = "A a; a = mock(A.class);";
		setup(javaCode);
		when(bindingHandler.getTypeName(Matchers.any(Type.class))).thenReturn("A");
		findMocks();
		assertThat(foundMocks.isEmpty(), is(false));
	}
 
	@Test
	public void canFindMocksWithProperNamesForDeclarationAndAssignment() throws Exception {
		String javaCode = "A a1 = mock(A.class); B b2; b2 = mock(B.class);";
		setup(javaCode);
		when(bindingHandler.getTypeName(any(Type.class))).thenReturn("A");
		when(bindingHandler.getTypeName(any(Expression.class))).thenReturn("B");
		findMocks();
		assertThat(foundMocks.get(0).getObjectName(), is("a1"));
		assertThat(foundMocks.get(0).getTypeName(), is("A"));
		assertThat(foundMocks.get(1).getObjectName(), is("b2"));
		assertThat(foundMocks.get(1).getTypeName(), is("B"));
	}
 
	@Test
	public void canFindMockAlsoIfItIsASpy() throws Exception {
		String javaCode = "A a = spy(new A());";
		setup(javaCode);
		when(bindingHandler.getTypeName(Matchers.any(Type.class))).thenReturn("A");
		findMocks();
		assertThat(foundMocks.isEmpty(), is(false));
	}
 
	private void setup(String javaCode) {
		createAst(javaCode);
		prepareBindingHandler();
	}
 
	private void createAst(String javaCode) {
		ASTParser newParser = ASTParser.newParser(AST.JLS3);
		newParser.setKind(ASTParser.K_STATEMENTS);
		newParser.setSource(javaCode.toCharArray());
		ast = (Block)newParser.createAST(new NullProgressMonitor());
	}
 
	private void prepareBindingHandler(){
		bindingHandler = mock(BindingHandler.class);
	}
 
	private void findMocks() {
		FindMockedObjects finder = new FindMockedObjects();
		finder.setBindingHandler(bindingHandler);
		ast.accept(finder);
		foundMocks = finder.getFoundMocks();
	}
}

I created no @Before method because the state I am testing on is different from test to test. So I am reusing by extracting the logic in private methods and calling them in every test with different parameters. I have to copy and paste code though. This problem will be addressed in next posts.

So any way, the visitor can evaluate the AST, but we also need it to be binded because of Type name of mocked object.

	@Override
	public boolean visit(MethodInvocation node) {
		if(isMockingMethod(node)){
			VariableDeclaration variableDecl = getParent(node, VariableDeclarationFragment.class);
			if(variableDecl != null){
				String objectName = variableDecl.getName().getIdentifier();
				VariableDeclarationStatement parent = getParent(variableDecl, VariableDeclarationStatement.class);
				Type type = parent.getType();
				foundMocks.add(new MockedObject(objectName, bindingHandler.getTypeName(type)));
				return true;
			}
			Assignment assignment = getParent(node, Assignment.class);
			if(assignment!=null){
				Expression leftHandSide = assignment.getLeftHandSide();
				if(leftHandSide instanceof SimpleName){
					SimpleName name = (SimpleName)leftHandSide;
					foundMocks.add(new MockedObject(name.getIdentifier(), bindingHandler.getTypeName(leftHandSide)));
					return true;
				}
 
			}
		}
 
		return true;
	}

So I extracted the logic that is depends on AST binding and put it in an extra class that I am mocking out in Test.

...
bindingHandler = mock(BindingHandler.class);
...
FindMockedObjects finder = new FindMockedObjects();
finder.setBindingHandler(bindingHandler);
...
when(bindingHandler.getTypeName(Matchers.any(Type.class))).thenReturn("A");
...

This way I can concentrate myself on the actual AST visiting and check binding resolving.
I another test.

posted by admin in to Test or not to Test and have No Comments

Check parser, understand Matcher

Now we want to check what we get from AST parser.

For this cause we need more consumers with deeper expectations.

As I will test only single behavior, it is better to put it in an setup method of the test class

        private ASTNode ast;
        ...
        @Before
	public void createAst() {
		String javaCode = "class A {}";
		ASTParser newParser = ASTParser.newParser(AST.JLS3);
		newParser.setSource(javaCode.toCharArray());
		ast = newParser.createAST(new NullProgressMonitor());
	}

The element that we get from AST parser is a compilation unit.
Compilation unit is a smallest chunk of code than can be compiled to binary.
In Eclipse AST class type hierarchy CompilationUnit is a subtype of ASTNode.

        @Test
	public void ensureThatParsedElementIsAnCompilationUnit() throws Exception {
		assertThat(ast, is(CompilationUnit.class));
	}

This looks like a simple and readable Expectation.
It also shows us that “is” Method can be used with a Class instance.

I already explained that “assertThat” uses Matchers to validate assumptions. But how does it work. The Hamcrest Tutorial is a very good place to lookup everything you need.

Any way I would like to introduce another test. It will expect the compilation unit to provide types and one of this types should be our A class.
So hear is the test:

        @Test
	public void ensureThatCompilationUnitHasTypeCalledA() throws Exception {
		CompilationUnit cu = (CompilationUnit)ast;
		List<AbstractTypeDeclaration> allTypes = cu.types();
		assertThat(allTypes, is(notNullValue()));
		assertThat(allTypes, hasItem(isTypeWithName("A")));
	}

And this test is also pretty self explaining and readable.
Here you can see the real power of Matcher. Matcher can be combined with each other and you can also provide your own matcher as I did with “isTypeName”.
So you don’t have to write code for iterating through collection, just nest two Factory Methods will do the trick.

Here is the code of the Matcher I wrote to evaluate a type declaration.

public class TypeHasName extends BaseMatcher<AbstractTypeDeclaration>{
 
	private final String name;
 
	public TypeHasName(String name) {
		this.name = name;
	}
 
	@Override
	public boolean matches(Object item) {
		AbstractTypeDeclaration type = (AbstractTypeDeclaration)item;
		return type.getName().getIdentifier().equals(name);
	}
 
	@Override
	public void describeTo(Description description) {
		description.appendText("type with name ").appendValue(name);
	}
 
	@Factory
	public static TypeHasName isTypeWithName(String typeName) {
		return new TypeHasName(typeName);
	}
}
posted by admin in to Test or not to Test and have No Comments

Git for that

By the way I created a Git repository for MockitoViz
http://github.com/mzaks/MockitoViz

Every post with examples will be tagged in repository.

posted by admin in to Test or not to Test and have No Comments

Ready, Steady, Go!

What do we need to start a Test driven Eclipse Project.

Well, first of all we need Eclipse RCP!
Than we create two PlugIn project MockitoViz and MockitoVizTest. (It is better to create create two projects so you don’t mix productive code with test code)

I saw an opening sequence of introduction to TDD from Kent Beck on vimeo. (by the way Kent Beck is the Father of XP, TDD and JUnit) And he introduced some interesting idea to me.

Mostly if I would start with Test first approach, I would start with theoretical classes that I would create and instantiate in my test (Programming by intention style), the test will not be compilable so I will have to create this classes. So in other word you create a consumer for something that does not yet exist and it’s kind of picky because you directly making assumptions about something.

Kent Beck started to implement the logic directly in the test and then extracted it to a Class under test. So if I would transfer it to my Consumer metaphor:

Do something your self, than delegate it to somebody else and check if he doing it write.

Now back to the real implementation and why I mentioned this stuff.
I created two projects and I know that I would need “org.eclipse.jdt.core” plugin for code evaluation. So I start with a test for parsing Java Code. I add two dependencies to my test Plugin:
- already mentioned “org.eclipse.jdt.core”
- and JUnit 4.

Now I implement something like this:

package de.bomzhi.jdt.exploration;
 
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
 
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.junit.Test;
 
public class ExploreParser {
 
	@Test
	public void parseSimpleClassDeclaration() throws Exception {
		String javaCode = "class A {}";
		ASTParser newParser = ASTParser.newParser(AST.JLS3);
		newParser.setSource(javaCode.toCharArray());
		ASTNode ast = newParser.createAST(new NullProgressMonitor());
		assertThat(ast, is(notNullValue()));
	}
}

By implementing this code I see that I need another two plugins:
- “org.eclipse.core.resources” because of IProgressMonitor that is used in “createAST” method
- and “org.eclipse.core.runtime” that is used internally by ASTParser

So here you see a client that converts a string to AST (Abstract Syntax Tree) and checks if he was successful. It has no expectations about the AST it becomes. The client is just happy that AST is not null.

By the way I am using the assertThat function for checking the assumption. assertThat was introduced in JUnit 4 and is based on matchers from Hamcrest framework.
Matchers provides pretty cool DSL for assertions. The error messages are also very readable.

Never the less, in this first short cast we created a first test which learns us how to use Eclipse ASTParser.

posted by admin in to Test or not to Test and have No Comments

Motivation Nr. 2

Lately I was experimenting with code evaluation and visualization in Eclipse.

So why shouldn’t I create a code visualization PlugIn for Eclipse while discussing about Testing.

And what should I visualize?

Well I planned to use Mockito as mocking framework anyway. Wouldn’t it be great if I would create a plugin that will visualize the mocked objects?

I think it would, so let’s start…

posted by admin in to Test or not to Test and have No Comments

Motivation

For me to test or not to test is not a question.

As a “lightly” paranoid person I like to know if my work does what it suppose.
And how do I achieve that knowledge?
I try it out!
I become a customer of my own code.

Automatic tests has the same assignment. They use the code and they complain if this code does something they don’t expect it to do.

So by providing automatic test you provide your system with users.
And how do you understand a system?
By looking how it is used.

That means that you score two times. You satisfy you paranoia and give people information how they could use your code.

Second task could be achieved by documentation. But documents could lie. Tests become red when they do.

posted by admin in to Test or not to Test and have No Comments

Summary on AS3 Creative point of view

I don’t think I would write something new to this topic because this year I kind of changed my sphere of action.

And to summarize the category I would like to post a link to the talk I gave on Adobe User Group Nederland.

It’s kind of embarrassing for me, because this video doesn’t put my presentation skills at the glance, but the content is quit interesting in my opinion. It is quit long though, it was a strange slot on this conference I got two hours. Too short for a tutorial and pretty long for a talk. But enough with explanations, here it is:

http://www.adobeusergroup.nl/site/list_messages/391

posted by admin in AS3 Creative point of view,IDE and have No Comments

Contraversive view on OO and Agile

http://www.infoq.com/interviews/coplien-dci-architecture

posted by admin in videos and have No Comments

Education Thoughts

Fast Food Education

Math Education

Sex Education

God Education

posted by admin in videos and have No Comments