db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Apache Wiki <wikidi...@apache.org>
Subject [Db-derby Wiki] Update of "IntroToJUnit" by SusanCline
Date Tue, 29 Aug 2006 21:45:00 GMT
Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Db-derby Wiki" for change notification.

The following page has been changed by SusanCline:
http://wiki.apache.org/db-derby/IntroToJUnit

New page:
=An Introduction to JUnit=

==Topics==

 1 Introduction to JUnit
 2 Where to get JUnit
 3 Running the Examples
 4 JUnit API
 5 Creating your First Test (Command Line and Eclipse)
 6 Fixtures
 7 Suites
 8 More about Assertions
 9 JUnit tests and the Derby test harness
 10 Resources


==Introduction to JUnit==

Writing tests during development
Code a little, test a little, ad infinitum
Provides the structure of a test case and tools 

       Test Case - junit.framework.TestCase

	Tools - junit.textui.  \
                junit.awtui.  --  TestRunner 
                junit.swingui. / 
Test case
	Create the objects
	Exercise the objects
	Verify the results

More info: JUnit Test Infected: Programmers Love Writing Tests
In the installed documentation: junit3.8.2/doc/testinfected/testing.htm

==Where to get JUnit==

http://prdownloads.sourceforge.net/junit/
The Derby tests have been run against 3.8.1 
Version 3.8.2 has been tested and the message reporting gives more context
Download junit3.8.2.zip
Unzip it
Includes documentation and javadoc (API)

Example of 3.8.2 improvement:
expected:<...st of the emergency [broadcasting] system> but was:<...st of the emergency
[locating] system> 

==Running the Examples==

%JUNIT_HOME%/junit/samples
Add junit.jar to your class path 

C:\junit\junit3.8.2>set CLASSPATH=junit.jar;.

C:\junit\junit3.8.2>java junit.textui.TestRunner junit.samples.AllTest
s
.........................................
.........................................
.........................................
........
Time: 0.811

OK (131 tests)

==JUnit API== 

junit.framework.Test Interface has two methods
	countTestCases() - counts the number of test cases this test (java class) will run
	run(TestResult) - Runs a test and collects its result in a TestResult instance

junit.framework.Assert - contains multiple static assert methods
	assertEquals() methods with different parameters (overloaded method)
       assertFalse()
	assertNotNull()
	assertNotSame()
	assertNull()
	assertSame()
	assertTrue(boolean)
	fail(String message)

junit.framework.TestCase implements Test and extends Assert - contains convenience methods:
	runTest() - the test(s) to run
	setUp() - initialize test variables, open network connections, etc.
	tearDown() - closes resources
        
Your class must extend junit.framework.TestCase
	

==Creating your First Test (Command Line and Eclipse)==

 1 Implement a subclass of TestCase (extend TestCase)
 2 Override the method runTest(), calling the tests to run
 3 Create a method to test, using one of the assertXXX methods to 
compare test values
	The method to test must start with the prefix 'test', e.g. 'testAddMethod'

Example of the simplest test case, containing only one test:
{{{
package junitdemo;

import junit.framework.TestCase;

public class FirstJUnitTest extends TestCase {

	protected void runTest() {
		testAdd();
	}

	public void testAdd() {
		int val1 = 5;
		int val2 = 6;
		int result = val1 + val2;
             // assertTrue method takes a boolean
		assertTrue(result == 11);
	}

}

}}}
====To test this class via the Command Line====

 1 make sure junit.jar is in your class path and the directory where the
	compiled classes reside
 2 compile the test
 3 run the test using the tool junit.textui.TestRunner


 1 C:\junit\junit3.8.2>set CLASSPATH=C:\junit\junit3.8.2\junit.jar;classes

 2 C:\junit\junit3.8.2> javac -d classes src/junitdemo/FirstJUnitTest.java 
   (places the compiled class in the classes directory)

 3 C:\junit\junit3.8.2>java junit.textui.TestRunner junitdemo.FirstJUnitTest
.
Time: 0

OK (1 test) 


====To create and test this class via Eclipse====

 1 While in the Java Perspective, right click in the Package Explorer View, New >> Project
>> Java Project, 
Provide a name >> Click Next. In the Java Settings screen select the Libraries
tab, then click the Add External JARs button. 

 2 Browse to junit.jar, then click Finish.

 3 Right click the Project, New >> JUnit Test Case, package = junitedemo, class name=FirstJUnitTest,

Superclass = junit.framework.TestCase, don't select any of the method stubs be created, leave
the Class under test blank, click 'Finish'.
	
 4 Add the two methods shown above, runTest() and testAdd(), and save the file. 

 5 To run the test right click FirstJUnitTest.java, Run As >> JUnit Test OR
	click the icon on the Menu Bar with the green circle and white arrow,
	Run As >> JUnit Test.

 6 A new view in Eclipse will appear as a JUnit tab and show if there were any
	Errors or Failures. 


==Fixtures==

The preceding example ran one test in one test class.  It's not very efficient
to build a test like that so let's create a Fixture of tests next.

A Fixture is used if you have more than one test that will operate on the
same or similar sets of objects. 

For a single test (method) contained in a single Test class these were the
steps we needed to do:

 1 Create a subclass of TestCase (extend TestCase)
 2 Override the method runTest(), calling the tests to run
 3 Create a method to test, using one of the assertXXX methods to 

For a fixture use these steps:

 1 Create a subclass of TestCase (extend TestCase)
 2 Add an instance variable for each part of the fixture
 3 Override setUp() to initialize the variables
 4 Override tearDown() to release any permanent resources you allocated in setUp()

Below is an example of a Fixture class which contains five tests to run.
(In reality you could have collapsed these tests into a fewer number.)

If you are using Eclipse to create this class, go ahead and select the main() and setUp()

method stubs be created this time. For the main() method, select 'Add TestRunner statement
for: text ui'.

For this example we'll show how to run a JUnit test case with a main() in it
instead of having to use the tool, junit.textui.TestRunner class, for our main
class. 

====JUnit Fixture class with a Main method====

package junitdemo;

import junit.framework.TestCase;

public class FixtureJUnitTest extends TestCase {

	protected int val1;

	protected int val2;

	protected String s1;

	protected String s2;

	public static void main(String[] args) {
		junit.textui.TestRunner.run(FixtureJUnitTest.class);
	}

	protected void setUp() throws Exception {
		super.setUp();
		val1 = 5;
		val2 = 6;
		s1 = "string1";
		s2 = new String("string1");
	}

	public void testAdd() {
		int result = val1 + val2;
		assertTrue(result == 11);
	}

	public void testStringEqual1() {
		// test to see if string s1 is equal to "string1"
		//assertEquals(String expected, String actual)
		assertEquals("string1", s1);
	}

	public void testStringEqual2() {
		// test to see if string s2 is equal to "string1"
		//assertEquals(String expected, String actual)
		assertEquals("string1", s2);
	}

	public void testStringSameObject1() {
		// assertSame(message, Object expected, Object actual)
		// should succeed because "string1".equals(s1)
		assertSame("Fail: string1 is not the same as s1", "string1", s1);
	}

	public void testStringSameObject2() {
		// should fail because "string1" not equal to new String("string1")
		assertSame("Fail: string1 is not the same as s2", "string1", s2);
	}

}

To run this class via Eclipse select Run As >> Java Application.

To run this class via the Command Line:

Set the class path: 

C:\junit\junit3.8.2>set CLASSPATH=C:\junit\junit3.8.2\junit.jar;classes

Compile the class:

C:\junit\junit3.8.2>javac -d classes src/junitdemo/FixtureJUnitTest.java

Run the class (since there is a main method, just run it normally):

C:\junit\junit3.8.2>java junitdemo.FixtureJUnitTest
.....F
Time: 0
There was 1 failure:
1) testStringSameObject2(junitdemo.FixtureJUnitTest)junit.framework.AssertionFai
ledError: 
        Fail: string1 is not the same as s2 expected same:<string1> was not:<s
tring1>
        at junitdemo.FixtureJUnitTest.testStringSameObject2(FixtureJUnitTest.jav
a:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.
java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcces
sorImpl.java:25)
        at junitdemo.FixtureJUnitTest.main(FixtureJUnitTest.java:16)

FAILURES!!!
Tests run: 5,  Failures: 1,  Errors: 0


Looking at the output you can see that our test called testStringSameObject2
failed with our custom message: Fail: string1 is not the same as s2.

JUnit added: expected same:<string1> was not:<string1>, and the stack trace
shows the line number of the failure as well.

If you prefer to create your fixture classes without a main (which is probably
the case if you will be integrating them into the derby harness) just do the
following;

1) remove the main method from FixtureJUnitTest
2) run the class with the junit.textui.TestRunner class like before

C:\junit\junit3.8.2>java junit.textui.TestRunner junitdemo.FixtureJUnitTest

7. Suites
*********

A TestSuite is the smallest execution unit in JUnit.   

To run all of the tests in a class do the following:

a) Create a one arg constructor which takes a String - the name of the method to run
b) create a suite() method which returns an implementation of the Test Interface,
	e.g. TestSuite

The class below, SuiteJUnitTest.java demonstrates this.

Running a Suite of Tests
------------------------

package junitdemo;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;
import junit.framework.TestSuite;

public class SuiteJUnitTest extends TestCase {

	protected int val1;

	protected int val2;

	protected String s1;

	protected String s2;
	
	public SuiteJUnitTest(String arg0) {
		super(arg0);
	}
	
      // to run all tests in this class

	public static Test suite() {
		return new TestSuite(SuiteJUnitTest.class);
	}
	
	protected void setUp() throws Exception {
		super.setUp();
		val1 = 5;
		val2 = 6;
		s1 = "string1";
		s2 = new String("string1");
	}

	public void testAdd() {
		int result = val1 + val2;
		assertTrue(result == 11);
	}

	public void testStringEqual1() {
		// test to see if string s1 is equal to "string1"
		//assertEquals(String expected, String actual)
		assertEquals("string1", s1);
	}

	public void testStringEqual2() {
		// test to see if string s2 is equal to "string1"
		//assertEquals(String expected, String actual)
		assertEquals("string1", s2);
	}

	public void testStringSameObject1() {
		// assertSame(message, Object expected, Object actual)
		// should succeed because "string1".equals(s1)
		assertSame("Fail: string1 is not the same as s1", "string1", s1);
	}

	public void testStringSameObject2() {
		// should fail because "string1" not equal to new String("string1")
		assertSame("Fail: string1 is not the same as s2", "string1", s2);
	}

}

If you want to specifically name which methods to run in the suite (for
instance if you don't want to run all of them) change the above suite() method
to this:

	// only adds two tests to the suite
	public static Test suite() {
		TestSuite suite = new TestSuite();
		suite.addTest(new SuiteJUnitTest("testAdd"));
		suite.addTest(new SuiteJUnitTest("testStringEqual1"));
		return suite;
	}

The output from running the modified SuiteJUnitTest class, which only runs
two tests is shown below; 

C:\junit\junit3.8.2>java junit.textui.TestRunner junitdemo.SuiteJUnitTest
..
Time: 0

OK (2 tests)

Creating Suites from different Java classes 
-------------------------------------------

You can also create a class that acts as sort of a harness that
runs suites from two or more classes.  An example of this is shown
below.  Also, you do not have to create a special class to run tests
from other classes, you could have one class that adds tests from it's
own suite and adds tests from another class too.

package junitdemo;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;
import junit.framework.TestSuite;

public class SuiteHarnessJUnitTest extends TestCase {
	
	public SuiteHarnessJUnitTest(String arg0) {
		super(arg0);
	}
	
	// Adds two suites to this suite
	public static Test suite() {
		TestSuite suite = new TestSuite();
		// the SuiteTest1JUnitTest class has two tests in it's suite
		suite.addTest(SuiteTest1JUnitTest.suite());
		// the SuiteTest2JUnitTest class has one test in it's suite
		// so a total of three tests will be run
		suite.addTest(SuiteTest2JUnitTest.suite());
		return suite;
	}
	
}


SuiteTest1JUnitTest
-------------------

package junitdemo;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class SuiteTest1JUnitTest extends TestCase {

	protected String s1;

	protected String s2;

	public SuiteTest1JUnitTest(String arg0) {
		super(arg0);
	}

	public static Test suite() {
		TestSuite suite = new TestSuite();
		// only add two tests from this class to the suite
		suite.addTest(new SuiteTest1JUnitTest("testStringEqual2"));
		suite.addTest(new SuiteTest1JUnitTest("testStringEqual1"));
		return suite;
	}

	protected void setUp() throws Exception {
		super.setUp();
		s1 = "string1";
		s2 = new String("string1");
	}

	public void testStringEqual1() {
		// test to see if string s1 is equal to "string1"
		//assertEquals(String expected, String actual)
		assertEquals("string1", s1);
	}

	public void testStringEqual2() {
		// test to see if string s2 is equal to "string1"
		//assertEquals(String expected, String actual)
		assertEquals("string1", s2);
	}

	public void testStringSameObject1() {
		// assertSame(message, Object expected, Object actual)
		// should succeed because "string1".equals(s1)
		assertSame("Fail: string1 is not the same as s1", "string1", s1);
	}

	public void testStringSameObject2() {
		// should fail because "string1" not equal to new String("string1")
		assertSame("Fail: string1 is not the same as s2", "string1", s2);
	}

}


SuiteTest2JUnitTest
-------------------

package junitdemo;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class SuiteTest2JUnitTest extends TestCase {

	protected int val1;

	protected int val2;

	public SuiteTest2JUnitTest(String arg0) {
		super(arg0);
	}

	public static Test suite() {
		TestSuite suite = new TestSuite();
		suite.addTest(new SuiteTest2JUnitTest("testSubtract"));
		return suite;
	}

	protected void setUp() throws Exception {
		super.setUp();
		val1 = 5;
		val2 = 6;
	}

	public void testSubtract() {
		int result = val2 - val1;
		assertTrue(result == 1);
	}

}

8. More about Assertions
************************

There are several assertXXX methods, and the examples so far have not
used very many of them.  Check out the javadoc that comes with JUnit
to get a more thorough explanation of these methods.

   JUnit_Install_Dir/javadoc/junit/framework/Assert.html


Several of these are overloaded to take a String message to customize the
error message, we saw that a little bit earlier.

Below are some code snippets that show examples of using the various
assert methods.

assertEquals
------------

Overloaded for almost all primitive data types and the Object arguments.

double expected = java.lang.StrictMath.acos(testArcValues[i]);
double rValue = executeValues("ACOS", testArcValues[i]);
assertEquals(expected, rValue, 0.0);

assertFalse
-----------

Takes a boolean argument.  Could use in place of assertTrue(boolean)

int result = val1 + val2;
assertFalse(result == 10);

assertNotNull
-------------

Takes an object with an optional second argument, the String message.

s2 = new String("string1");
assertNotNull("Fail: Object s2 is null. ", s2);

assertNotSame
-------------

Takes two objects with an optional third argument, the String message.

s2 = new String("string1");
assertNotSame("Fail: string1 is the same as s2", "string1", s2)

assertNull
----------

Takes an object with an optional second argument, the String message.

Object nullObj = null;
assertNull("Fail:object was not null", nullObj);

assertTrue
----------

int val1 = 5;
int val2 = 6;
int result = val2 - val1;
assertTrue(result == 1);

fail
----

Fail takes one argument, the String message output and is used to fail a test.

Why would you want to use this?  For instance if you are performing some
action that should throw an exception and you don't know whether the exception
was thrown or not.  Since JUnit does not output exceptions, just failures,
use fail to fail the test if the exception was not thrown.

try {
     // for the value TWO_RADIANS, this method should throw
     // an SQLException in Derby
     executeValues("ACOS", TWO_RADIANS);
     fail("ACOS: Out of range test failed, input value is: "
					+ TWO_RADIANS);
    } catch (SQLException sqlE) {
       // "ERROR 22003: The resulting value is outside the range for the data type DOUBLE.";

9. JUnit tests and the Derby test harness
*****************************************

CAVEATS: 
I don't know the Derby test harness
Dan is changing the design of the JUnit suite stuff as we speak

But, as of 8/28/ the below works for this one test ;-)

a) Create a JUnit test that extends the Derby class BaseJDBCTestCase
(org.apache.derbyTesting.junit.BaseJDBCTestCase) and put it in the correct 
package name space of the Derby test harness.  
For instance, org.apache.derbyTesting.functionTests.tests.lang

b) Add a public constructor to your test class that takes a String argument 

public MathTrigFunctionsTest(String name) {
  super(name);
}

c) Create a setup and teardown class which make use of some of the BaseJDBCTestCase utilities
to get the connection and use a default database.

...

private Connection conn;

...

public void setUp() throws Exception {
  conn = BaseJDBCTestCase.getConnection();
  conn.setAutoCommit(false);
}

public void tearDown() throws SQLException {
  conn.rollback();
  conn.close();
}

d) Place your java class in the derby source tree in the appropriate 
directory according to the package name.  For instance my Derby source
directory is C:\derby_src\trunk\, so the
directory I put the MathTrigFunctionsTest.java class is
C:\derby_src\trunk\java\testing\org\apache\derbyTesting\functionTests\tests\lang 

e) Make sure the Derby source classes directory, junit.jar and 
jakarta-oro-2.0.8.jar files are in your class path.

f) Edit the file derbylang.runall in the 
$DERBY_SRC/trunk/java/testing/org/apache/derbyTesting/functionTests/suites 
directory with the name of your java class, but with a .junit extension, preceded
by the directory name where the class resides.  For instance with the MathTrigFunctionsTest

which resides in the functionTests/tests/lang directory, this is the entry in the
derbylang.runall file:

lang/MathTrigFunctionsTest.junit

g) To test your class
	ant clobber
	ant all
	java org.apache.derbyTesting.functionTests.harness.RunTest lang/MathTrigFunctionsTest.junit


   To run all the tests in the derbylang suite use this command:

	java org.apache.derbyTesting.functionTests.harness.RunSuite derbylang


10. Resources
*************

JUnit Docs: Installed with JUnit zip file, also available at JUnit:
http://junit.sourceforge.net/

JUnit FAQ:
http://junit.sourceforge.net/doc/faq/faq.htm

The Derby wiki:
DerbyJUnitTesting,
http://wiki.apache.org/db-derby/DerbyJUnitTesting

DerbyJunitTestConfiguration,a new page that is under construction 
(as mentioned above Dan is trying to set up/change the way we do JUnit with Derby),
http://wiki.apache.org/db-derby/DerbyJunitTestConfiguration

Note: This will probably invalidate the stuff I have above about using
JUnit with the Derby test harness. 

Eclipse JUnit Getting Started
Open Eclipse Help from the main menu item, select the Java Development User Guide book, 
Getting Started >> Basic tutorial, Writing and running JUnit tests.

There is additional information in here that I did not cover such as running
a single test method from a class and creating suites.

Eclipse JUnit Tutorial - Third Party
http://open.ncsu.edu/se/tutorials/junit/

Mime
View raw message