Thursday Jun 22, 2006

P2P programming

Few years ago has been introduced XP programming. A part of XP programming was pair programming. What is pair programming? Two developers are programming together on one computer. They are reviewing their ideas in one time. It rapidly increased quality of code.

Pair and XP programming is applicable to small teams. It is quite difficult to use XP methods on project where are for example hundreds developers. What is missing here? The developers didn't provide inter team communication about their codes. It is really difficult to share knowledge among all the developers.

Another way how to review the code is send commit logs to public mailing list. The commit logs are read only inside small team because it is not effective if the developers checks commit logs from many developers.

An inspiration how to solve this problem can be P2P data sharing. P2P data sharing was invented in order to reduce load of server. Big file is split to many small parts. Different parts are distributed to different users(nodes). If the node download his part he can redistribute the parts to different users. For each node in P2P network is computed ration uploaded/downloaded. When the ratio is very small the node got smaller priority for downloading files than node with bigger priority.

We can map P2P networking problem to code review problem. A node is developer. A developer commits code.Other developers reviews his code. It is the same like P2P network. The download is reviewing his code. The upload is reviewing of other's developer code. If the developers doesn't review code. No one is interested in review his code because the commit log is on the end of list with commits for code review.

The commits log are sent to different groups of developers. How to distinguish the developers? There are few metrics: -A developer uses a API. The API owner is in commit logs. The api usage is in commit log of the the user. The owner of API do the review. -He uses the API for long time I got many reviews. He is experienced API user. He can do review of code which uses the API or do the review to API developer Sent the same count of commit logs to different developers.

The reviewer must mark the reviewed code:

  • The code is good
  • The code is wrong

He can also add comments to review.

For the code review can be created a plugin to IDE.

The P2P programming can be used for code evaluation between different projects if they uses the same API or export API. For example first group develops WEB framework. The second group develops web application. The second group uses the framework of the first group. The first group do review of the code of the second group. After a while third group of developers started use the API of the first group. The code of third group will can review second group because they are experiences users of the framework.

Please let me know if already exists software project similar to P2P programming.

Wednesday May 31, 2006

Testing memory leaks with assertGC

I was talking about assertSize in one of previous entry about testing. NbTestCase class contains more useful methods. Today I will be talking about assertGC method. The assertGC method tests tries to run garbage collect with different methods and then scan if exists path to reference in memory by using insane library. Look at simple example:

public class LeakTest extends NbTestCase {
    
    public LeakTest(java.lang.String testName) {
        super(testName);
    }
    public void testLeak() {
        String obj = new String("test1");
        WeakReference ref = new WeakReference(obj);
        obj = null; 
        assertGC("pass",ref);
        obj = new String("test2");
        ref = new WeakReference(obj);
        assertGC("fails",ref);
    }
    
    public static Test suite() {
        TestSuite suite = new NbTestSuite(LeakTest.class);
        return suite;
    }
}

First asertGC passed because in JVM exists only WeakReference for object String("test1"). The second assertGC failed because the reference obj holds String("test2").

Tuesday May 23, 2006

Test size of your data structures in Unit Test

Petr Nejedly invented interesting tool for measuring memory usage of data structures on java heap. Name of the tool is Insane. Pages of the tools are here. It uses Java introspection to traverse all fields and references in graph of data structure. It allows to exclude traversing for specified references. Insane was integrated with NBJunit library. NBJunit is extension of Junit 3.x. It was designed in order to test NetBeans IDE. In this article I try show power of Insane library inside NBJunit.

NBTestCase class is supper class of for NetBeans test. It extends from Junit TestCase. The NBTestCase contains assertSize methods for testing size of java structures. For example we want to measure size of NumList class:

    public static class NumList {
        public int num;
        public NumList next;
    };

A instance of the class takes 16 bytes on the heap on 32bit virtual machine. A simple test for this structure can look like this:

  public void testA() {
        NumList item = new NumList();
        // 1. test one instance   
        assertSize("NumList a",16,item);
        // 2. test size of instances in collection 
        assertSize("NumList a",Collections.singleton(item),16);
        NumList item2 = new NumList();
        item.next = item2; 
        // 3. test linked structure 
        assertSize("NumList a",Collections.singleton(item),32);
        // 4. ignore the item2 references
        assertSize("NumList a",Collections.singleton(item),16,new Object[]{item2});
    }

The test passed when the size of the structure doesn't exceed the defined limit (16 or 32 bytes). Interesting is use case on line number four

assertSize("NumList a",Collections.singleton(item),16,new Object[]{item2});

The last parameter tells that the measurement won't traverse through item2 reference. It is very useful when we measure only subset of complicated structure.

The test passed. Why the instance of NumList takes 16 bytes in memory of 32bit JVM?

  • 8 bytes are for object header
  • 4 bytes are allocated for num variable
  • 4 bytes are allocated for reference to next NumList
We can start to experiment with our structure. We add one field to NumList class:

    public static class NumList {
        public int num;
        public int num2;
        public NumList next;
    };

We run the test again. The test fails with message:

Testcase: testA(MemoryTest):	FAILED
NumList a: leak 8 bytes  over limit of 16 bytes
  MemoryTest$NumList: 1, 24B

junit.framework.AssertionFailedError: NumList a: leak 8 bytes  over limit of 16 bytes
  MemoryTest$NumList: 1, 24B

        at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1108)
        at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1065)
        at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1050)
        at org.netbeans.junit.NbTestCase.assertSize(NbTestCase.java:1039)
        at MemoryTest.testA(MemoryTest.java:28)
 

Instance takes 24 bytes in memory now. How is it possible if the int type tales 4 bytes in memory? Yes it takes four bytes. The instance takes 24 bytes on heap because the size of java object is aligned to 8 bytes. So we will fix the test for new NumList version.

  public void testA() {
        NumList item = new NumList();  
        assertSize("NumList a",24,item);
        assertSize("NumList a",Collections.singleton(item),24);
        NumList item2 = new NumList();
        item.next = item2; 
        assertSize("NumList a",Collections.singleton(item),48);
        assertSize("NumList a",Collections.singleton(item),24,new Object[]{item2});
       
    }

The test passed now. The instance is aligned to 8 bytes as I wrote. Why to no try add one more varible to TestNum structure? The new version is below.

    public static class NumList {
        public int num;
        public int num2;
        public int num3;
        public NumList next;
    };

This version does't need more memory than the previous. We can check it by running the test. Yes, the test passed now. Isn't combination of Insane ane NbJUnit great idea?

Monday May 15, 2006

TestNG over beats JUnit ?

GlassFish project quality team chose TestNG framework for testing. Why did they make the decision? They compared the both tools in this document.

It looks like war Eclipse versus NetBeans. NetBeans dominate five years ago in Java IDE's. NetBeans had few dessign problems and almost no innovation. Therefore Eclipse eclipsed NetBeans. But the situation is quite different now. There was many new features in NetBeans 5.0. Everything is in one pack (J2SE, J2EE, J2ME, profiler). The NetBeans team is focused on usability. Many 3rd party plugins are available on nbextras.org NetBeans 5.5 beta with EJB support has been released. Completely new java editor will be in NetBeans 6.0.

. And eclipse? Yes there exists many plugins for eclipse. But with different UI and the plugins are not compatible. No it is no end of Eclipse. It's challenge for Eclipse team. They also need to innovate. So who wins the war between two java opensource IDE's? I think the user. He will have two powerful java IDE's. Isn't great to have two different opensourced java IDE's in the world?

Back to subject TestNG versus JUnit 4. What is idea of TestNG? I think:

  • Support features which are missing in JUnit
  • Simple usage. Only one jar without dependencies on 3rd party libraries and simple API.
So Junit needs to innovate. To copy features from TestNG is not enough.

Saturday May 13, 2006

Mocking final classes with BCEL, java.lang.instrument and EasyMock

I've introduced EasyMock library in previous entry of testing category. I read in documentation of EasyMock that final methods cannot be mocked. I've found solution of this problem for testing with Jmock library. Bytecode of the class is changed before the class is loaded. The solution also works for EasyMock. I'll describe how to do it in next paragraphs.

The Byte Code Engineering Library (BCEL) library provide simple way how to navigate and change bytecode of java classes. I used this library in order to remove final flag from classes. It is only few lines by using this library.

Java.lang.instrument provides services that allow Java programming language agents to instrument programs running on the JVM. Nice article about it is here. I used java.lang.instrumnet for changing bytecode during classloading.

Example with removing final flag is below. Transf class is implementation of java.lang.instrument service. It is not difficult to add removing of final flag for methods of class to code. I created this example to demonstrate how powerful is java.lang.instrument service.

 
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
....

public class Transf implements ClassFileTransformer {
	public byte[] transform(ClassLoader loader, 
                                String className, 
                                Class redefiningClass, 
                                ProtectionDomain domain, 
                                byte[] bytes) throws IllegalClassFormatException {
                try {
                    ClassParser parser = new ClassParser(new ByteArrayInputStream(bytes),className);
                    JavaClass clazz = parser.parse();
                    clazz.setAccessFlags(clazz.getAccessFlags() & (~Constants.ACC_FINAL ));
                    bytes = clazz.getBytes();
                    System.out.println("Transformed Class: " + className);
                } catch (ClassFormatError ex) {
                    ex.printStackTrace();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            return bytes;
	}
}

To initialize the class patching agent it is necessary to create premain class:

public class SimpleMain {
	public static void premain(String agentArguments, Instrumentation instrumentation) {	
		instrumentation.addTransformer(new Transf());
	}	
}
The referece of the premain class is specified in MANIFEST.mf of build jar with java agent.
 
Manifest-Version: 1.0 
Premain-Class: mypackage.SimpleMain
When we run tests we need to say java where the java agent service is located by using -javaagent parameter.
java -javaagent:classpatching.jar ...

Thursday May 11, 2006

Test Patterns In Java™ Technology Development on Java One

Are you going on Java One? Don't forget on Test Patterns In Java™ Technology Development session.

  • Tuesday , 05/16/2006, 09:30 PM - 10:20 PM BOF-0220

Three architects of NetBeans (Jesse Glick, Jaroslav Tulach, Milos Kleint) will be talking about their experiences with test driven development. To tell you truth, these guys save me a lot of time in my work. Yes, they are careful and write tests whether it is possible. Almost no regression is in their code. I than can cover more features as QA representative.

I tell you a success story with test driven development. Jaroslav Tulach is one of the NetBeans fathers. I remember times when he started to write tests. He wrote API of NetBeans. Many developers dependent on his code. Before four years every one in NetBeans were afraid of his commits. A small change in code on which depends many developers caused the break of NetBeans build. But now he write also a lot of code. But the code is already tested with unit tests. And the code is really stable. Every one writes code with mistake. With test the code contains a little count of bugs and we are able to catch regressions earlier with daily tests runs.

I learn from Jaroslav's and Jesse's code a lot of useful testing pattern. Therefore I recommend the session.

Session Abstract

Testing is an important part of software development. Effective testing is a key factor in reducing total cost of maintenance of any application over its lifetime. It reduces the cost and time of development and can increase savings on quality assurance. Knowing when to invest in better design, in postdevelopment quality assurance, in manual tests, or in automatic testing forms a basic difference between successful and unsuccessful software projects in these tough and competitive days.

This presentation starts with general motivation and presents automatic tests as a form of functional specification. It then quickly delves deep down into hard-core JUnit test examples showing various forms of regression tests verifying algorithm complexity, memory management, data structure sizes, deadlocks, race condition behavior and tests randomly generating new test cases, simulating user clicks in the UI, API signature tests, and so on.

Attendees should know what tests are and that tests are an important and useful part of software development. The presentation demonstrates practical usage of a test framework. You learn techniques, tips, and tricks for testing various aspects of real-world Java™ Platform, Standard Edition (Java SE) applications. The session also gives examples of the savings and improvements that were achieved by increased usage of extensive automatic testing in the development of the NetBeans™ IDE and platform.

Monday May 01, 2006

First Experience with EasyMock

I like test driven development. But I don't write tests for all features of my code because it is difficult to setup testing environment. For example it is difficult to set up unit test environment for NetBeans Java Model (API). There are too many dependencies. It is possible to run tests in running NetBeans (IDE mode). But I don't prefer this variant because it takes a lot of execution time. Therefore I didn't write tests for pieces code which uses JMI API.

I found regression in my code which work quite long time. So I designed to create Mock objects for few JMI interfaces. Mock objects is implementation of classes for testing purpose. Simply you write tests against API without its implementation, It's mean that you define a scenario of use case of API's pieces in your test. For example you want to to develop tests for application which uses jdbc connection to access data. To setup database is quite difficult. So you write tests without database. You need to simulate jdbc. In this case you can use already implemented mock objects for jdbc api. Developing JDBC applications test-first is nice article about mocking jdbc. Writing of test is simple when jmock library already exists for the API. But in many cases there is no jmock implementation for API which you are using and the api is not well designed for testing. But you want to write tests at least for the critical code. You will have to write jmock objects yourself. Fortunately you can use library for writing jmock object. I know two libraries for Java languages for this purpose:

I tried to use JMock library in the past. You can mock interface and classes. I don't like two things on JMock. JMock uses strings for mocked method names. I have bad memory and I am alredy got a customed to use code completion. The jmock was dessigned for junit 3.8. The recomended way how to use jmock is to use jmock's class like supperclass for yor test case. You don't need to extends your testcase but the code is not then so nice. Today I used Easy Mock it the first time. It is dessigned for TestNG and JUnit 4. It supports jdk 1.5. You can use static import if you don't want to write the classname in everytime. You can use code completion when you define the behavior of mocked code.

I describe my first unittest for code with JMI usage. Look at the code. The comments is bellow.


import java.util.\*;
import junit.framework.\*;
import org.netbeans.jmi.javamodel.Method;
import org.netbeans.junit.\*;
import static org.easymock.EasyMock.\*;

public class ElementTest extends NbTestCase {
....
 public void testParseUnknownTag() {
        Method m = createMock(Method.class);
        expect(m.getJavadocText()).andReturn("@myTag");
        expect(m.getAnnotations()).andReturn(Collections.EMPTY_LIST);

        replay(m);

        Element el = Element.findElement(m);
        assertNotNull(el);
        Tag tag = el.getTag("myTag");
        assertNotNull(tag);
        assertTrue(tag.getTagTemplate().isUnknown());
        assertTrue(m instanceof Method);
    }
... 
}   

In the code is tested parsing javadoc tags from Method element. The test is separed into three parts. In the first part is created jmock object for method element. The method contains javadoc with value "/\*\*@myTag\*/" and no annotations. No more methods is used in tested code so it is not necessary to have more mocking methods. The second part activates the mock object by invoking replay(m) method. The code is tested in the last part.

By EasyMock you can also check count of calls. Let's show example. A method's call is expensive. To be sure that the method is called only one time you can write mock object for the class of method. In the test will be tested if the method is called only one time.

Friday Apr 14, 2006

The best documentation of API - unit test

Developers don't like writing of documentation. Many tutorials and documentations are obsolete. I saw wrong javadoc comments sometimes. I claim that the best documentation of API are the unit tests.

  • The unit test cannot be obsolete if is run daily.
  • The unit test is tutorial of the tested code.
  • It contains recommended design patterns.
  • The code will be more reliable if already tested patterns are used.

For example I was reading javadoc of Java Language Model API (JMI). From the javadoc I didn't get knowledge how to read, create and modify annotations. Thanks to Google I found some unit tests of JMI module which uses annotations. I can use a pattern shown bellow in my code and I'm sure that it is good usage.

 public void testAddAnnotation() throws java.io.IOException, FileStateInvalidException {
        boolean fail = true;
        Utility.beginTrans(true);
        try {
            Method method = (Method) clazz.getContents().get(0);
            // log the annotation information
            getLog().println("Method '" + method.getName() + "' has following annotations:");
            for (Iterator it = method.getAnnotations().iterator(); it.hasNext(); ) {
                Annotation annotation = (Annotation) it.next();
                getLog().println("\\tAnnotation named '" + annotation.getType().getName() + "'.");
                for (Iterator it2 = annotation.getAttributeValues().iterator(); it2.hasNext(); ) {
                    AttributeValue attribute = (AttributeValue) it2.next();
                    getLog().println("\\t\\tAttribute value '" + attribute.getName() + "', '" + ((MetadataElement) attribute.getValue()).getSourceText() + "'.");
                }
            }
            Annotation ann = createSimpleAnn("\\"2004-06-21\\"", "\\"Lojza\\"", "\\"Unknown\\"", "46");
            method = (Method) clazz.getContents().get(1);
            method.getAnnotations().add(ann);
            fail = false;
       }
        finally {
            Utility.endTrans(fail);
        }
        assertFile("File is not correctly generated.",
            Utility.getFile(getDataDir(), "org/netbeans/test/codegen/AnnotationClass.java"),
            getGoldenFile("testAddAnnotation_AnnotationClass.pass"),
            getWorkDir()
        );
    }

I got a idea. Why not to add link to unit tests to javadoc html. TestNG uses annotations to specify tests groups. Why to not add annotations which package, class or method is tested. The link to test sources should be added to javadoc documentation. The test can be also indexed. Usage statistics can shown in javadoc. After that many developers, who don't write tests, will have to write tests I hope. Because the API users (developers) rather choose already tested API.

About

xzajo

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today