I've been a zone leader with DZone since 2008, and I'm crazy about community. Every day I get to work with the best that JavaScript, HTML5, Android and iOS has to offer, creating apps that truly make at difference, as principal front-end architect at Avego. James is a DZone Zone Leader and has posted 639 posts at DZone. You can read more from them at their website. View Full User Profile

Thursday Code Puzzler: Test Case Generator

11.15.2012
| 5844 views |
  • submit to reddit

 It's Thursday, time for our weekly code puzzler! The idea is simple: solve the coding problem as efficiently as you can, in any language or framework that you think is suitable.

Note: Even though there really is nothing stopping you from finding a solution to this on the internet, try to keep honest, and come up with your own answer.  It's all about the participation!

Test Case Generator

For those who don't follow pure test driven development, or are dealing with legacy code, it's sometimes necessary to write up suites of test cases to ensure everything works as expected. Today's challenge is to write a piece of code that inspects a Java class, and create a corresponding test class for it. As well as having tests for each method, you should consider the parameters, return types and exceptions along with the different possible ranges.

There's a few different ways to achieve this. If you wish, you can express the efficiency of the algorithm you come up with using Big O notation.

Catch up on all our previous puzzlers here

Comments

Stephane Vaucher replied on Sat, 2012/11/17 - 1:15pm

Love the puzzler. It's like: "How would you write an optimizing compiler for Java? You can use whatever language/tool you want."

1. Parse Java class

2. For every method, identify possible types of formal parameters (this is of variable complexity depending on the CHA you perform, aiming for perfection is NP-hard).

3.Determine how to instantiate these objects (NP-hard, or use a heuristic).

4. Generate code

Voila! Steps 1 and 4 are the trivial parts as you can use whichever tools you want. You probably want to extract an IR/call-graph from there. For 2, use a tool like Soot. For 3, have fun traversing call/control flow graphs in step 1. You might have to wait a while though. You can always cheat and produce suboptimal or incorrect results (well it is a prerequisite to have a presentable solution).

Vijay Nathani replied on Tue, 2012/11/20 - 9:22am

 Simple Test Generator in Groovy:

package p02

class TestCreator {
	static def skipMethods = [
		'equals',
		'hashCode',
		'notify',
		'notifyAll',
		'toString',
		'wait',
		'notify',
		'notifyall',
		'getClass'
	]
	final Class sut
	TestCreator(sut) {
		this.sut = sut
	}
	private def getMethodNames() {
		sut.metaClass.methods.collect { it.name }.unique().minus(skipMethods).sort()
	}
	private String getPackageName() {
		sut.canonicalName.replaceAll('\\..+',"")
	}
	private String getClassName() {
		sut.canonicalName.replaceAll('.+\\.',"")
	}
	private String generateTestForMethod(name) {
		"""	@Test
	public void ${name}_test() {
		//to be implemented
	}"""
	}
	def createTest() {
		def r = """package ${packageName}; 
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class ${className}Test {
"""
		r + methodNames.collect { generateTestForMethod(it) } .join("\n") + "\n}"
	}
}

/* //For Java class package p02;
public class Abc {
   public int f1() {
     return 0;
   }
}
//When run
package p02
class TestCreatorDemo {
   static main(args) {
     println new TestCreator(Abc.class).createTest()
   }
}
//The output is
package p02;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class AbcTest {
   @Test
   public void f1_test() {
     //to be implemented
   }
}
*/

Arindam Roychoudhury replied on Wed, 2012/11/21 - 12:51am


This is a complex problem. Generating effective test cases requires understanding the object graph of the system under test. There have been a few papers published on this. And there are very expensive industry standard tools for this too (like Jtest). Interested people can also check out Randoop for an open source implementation to understand the complexity involved: http://code.google.com/p/randoop/.

Marc Aurel replied on Thu, 2012/11/22 - 7:36am


Hello,

I'm sorry to say that, but Java is not the language that is suitable for such a task. In my opinion you could compare that task with the FTA (Fault Tree Analysis), but on a class level. What that means?

For example I don't know the exact purpose of the class, if I don't invent some kind of annotation to drive the unit test generator. I don't know which Errors are expected to happen at what state of execution, perhaps there might be some side effect for example, that is causing an error properly.

This is to say that one would have to say that a test writer has to think about the results of the function to test that it works as expected when some actual arguments of a Domain are passed. This is in no way computable. Because the program needs not only to know which errors can happen but also why they can happen.

 

So the solution of the groovy programmer seem to be the only way to. But that is script kiddie like.

 

Vijay Nathani

Vijay Nathani

 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.