Friday, February 15, 2008

Java: how to find the absolute path with white space to the resource ?

For example: our program contains the resource A and class MyClass


src
main
java
MyClass
resource
A


When we package our program, A will be at root.
To get the absolute path to resource(for example when we want to do unit test
and load those resource for test), we will call
String path = MyClass.getClass.GetResource("/A").toURI().getPath();
And now we have the absolute path to resource.

JMock and how to mock static function and final class?

Unit test is one of the "must" task when we develop software. One of the most technology we usually used is mock. As i already said in one of my previous post,
mock is the powerful technology but they have some limitation. This limitation is depend on which type of mock object( JMock, AMock, NMock ...) or the environment.
For example, if you want to test some DAO class which directly access to DBMS, you can not create mock for all JDBC class to do unit test. And in this case, we also can not do unit test because the test depend on the environment(we have to set up an DBMS just for do unit test). Therefore, we have to chose the most suitable way to test: System test, module test, review code ...
JMock like others mock object, has it own limitation. It can not mock final class, static method. It is because of its implementation. For final class, JMock can not inherit the class to create new mock class ==> can not mock this class.
With static method, because static method can not be overriden, so JMock has no way to create mock object.

So in this case, we have to think about design and test first before code
1. Case: our method use final class.

We will use pattern template method to separate code which contain instances of final class.


class OurClass {
function myFunc() {
my code
......
URL url = new URL(href); //Can not mock URL because of final class
url.openstream(...)
....
my code


}
}
Our mission is test this function.


In this case, we create new class calls MockHelperTest and a factory MockHelperFactory



IHelperFactory = interface{
IHelperTest getMockHelper;
}

MockHelperTest = class implements IHelperTest{

void funcHelper() {
///Prepare data , result and code for mock
}
}

and we change our class to:


class OurClass {
public IHelperFactory factory = null; //factory can be set by unit test

//If we test this function, we will
//pass mock factory to this class and
//function will call mock function
//instead of real code.
//If we want to to do real code,
//just pass null factory, and it will
//create real factory and then myFunc
//will call funcMockHelper which call
//real code:
//URL url = new URL(href); //Can not mock URL because of final class
//url.openstream(...)

OurClass(IHelperFactory mockFactory) {
if mockFactory == null ) {
factory = new RealFactory();
} else {
factory = mockFactory;
}
}

function myFunc() {

my code
......
IHelperTest helper = factory.funcHelper().getMockHelper();
helper.funcMockHelper();
....
my code
}
}



And now, we can easily replace the code which can not mock which the mock code.
The same pattern for static function.

Conclusion: Think about test + design first and then code.

Sunday, February 3, 2008

NUnit === How to and FAQ

NUnit goal:

+ NUnit is a unit-testing framework for all .Net languages. Initially ported from JUnit, the current production release, version 2.4, is the fifth major release of this xUnit based unit testing tool for Microsoft .NET. It is written entirely in C# and has been completely redesigned to take advantage of many .NET language features, for example custom attributes and other reflection related capabilities. NUnit brings xUnit to all .NET languages
Homepage: http://www.nunit.org/index.php

+ Why do we use NUnit?
Because it makes us do unit test very easy and very efficiently

+ How to use NUnit:

1.We have to import library:
using System;
using NUnit.Framework;
2. Declare[TestFixture] attribute to class
3. Declare [SetUp] attribute for setup function. This function will be called before any call to tested function
4. Run NUnit test GUI to test assemblies

+ Some functions need for test:
Assert.AreEqual: raise exception if two object are not the same
Assert.IsTrue: raise exception if condition is false
Assert.IsFalse: raise exception if condition is true
Assert.Fail: Raise exception to notify test case fail.
....

+ How do I implement a test case for a thrown exception?
Catch the exception and if it isn't thrown call the Fail method. Fail signals the failure of a test case. Here is an example:


public void TestArgumentOutOfRangeException() {
ArrayList l = new ArrayList(10)
try {
Object o= l[l.Count];
Fail("Should raise an ArgumentOutOfRangeException");
} catch (ArgumentOutOfRangeException) {
}
}

or use the ExceptionTestCase as follows.
1) make your TestCase class a subclass of ExceptionTestCase.
2) write the test ignoring exceptions

public void TestArgumentOutOfRangeException() {
ArrayList l= new ArrayList(10);
l[l.Count];
}

3) create the TestCase:

Test t= new ExceptionTestCase("TestArgumentOutOfRangeException", typeof(ArgumentOutOfRangeException))


Looking at this again, the first way is simpler. Sigh...

Another way:
Declare:


[Test]
[[ExpectedException( typeof( AException ) )]
void testFunction() {
...............
};



+ How do I organize my Test Cases?
Here is one way:

1. create a test namespace for each of your application namespaces. For example, for a namespace MyApp.Util define MyApp.UtilTest. Put all the fixtures for the Util namespace into this namespace.
2. in MyApp.UtilTest define a class which creates a suite with all the tests in this namespace. To do so define a class AllTests which includes a single static Suite property. Here is an example:

public static ITest Suite {
get {
TestSuite suite= new TestSuite();
suite.AddTest(Fixture1.Suite);
suite.AddTest(Fixture2.Suite);
return suite;
}
}


3. define similar AllTests classes that create higher level suites containing the suites from other test packages.

When the fixtures are in a separate test assembly the test cases don't have access to the methods and fields with internal visibility. A variation of the above convention is to put all fixtures into the application assembly itself. This gives the fixtures access to all the assembly visible methods and fields. To separate the fixture classes from the production classes put them into a separate directory that you then add to the project. This makes it easy to ship the production classes independent of the fixtures.

How do I run setup code once for all my TestCases?
Wrap the top level suite in a subclass of TestSetup. Here is a sample AllTests.Suite method:


protected class WrappedTestSetup: TestSetup {
public WrappedTestSetup(ITest test) : base(test) {}
protected override void SetUp() {
OneTimeSetUp();
}
};

public static ITest Suite {
get {
TestSuite suite= new TestSuite();
...add your tests and suites here...
TestSetup wrapper= new WrappedTestSetup(suite);
return wrapper;
}
}


+ I want to debug when a test fails
Start the test runner under the debugger and configure the debugger so that it catches the NUnit.Framework.AssertionFailedError. How you do this depends on the used IDE. Most debuggers support to stop the program when a specific exception is fired. Notice, that this will only break into the debugger when an "anticipated" assertion failed error occurs.

Steps:
1. Start C# IDE ( Visual .net ide)
2. Build project + test in debug mode.
3. Configure NUnit GUI to support VS.NET project
3. Add debug assembly to NUnit GUI.
4. Put breakpoint to where you want to debug
Finished.


Sample:


namespace NUnit.Samples.Money
{
using System;
using NUnit.Framework;
///
///
///

///
[TestFixture]
public class MoneyTest
{
private Money f12CHF;
private Money f14CHF;
private Money f7USD;
private Money f21USD;

private MoneyBag fMB1;
private MoneyBag fMB2;

///
///
///

///
[SetUp]
protected void SetUp()
{
f12CHF= new Money(12, "CHF");
f14CHF= new Money(14, "CHF");
f7USD= new Money( 7, "USD");
f21USD= new Money(21, "USD");

fMB1= new MoneyBag(f12CHF, f7USD);
fMB2= new MoneyBag(f14CHF, f21USD);
}

///
///
///

///
[Test]
public void BagMultiply()
{
// {[12 CHF][7 USD]} *2 == {[24 CHF][14 USD]}
Money[] bag = { new Money(24, "CHF"), new Money(14, "USD") };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, fMB1.Multiply(2));
Assert.AreEqual(fMB1, fMB1.Multiply(1));
Assert.IsTrue(fMB1.Multiply(0).IsZero);
}

///
///
///

///
[Test]
public void BagNegate()
{
// {[12 CHF][7 USD]} negate == {[-12 CHF][-7 USD]}
Money[] bag= { new Money(-12, "CHF"), new Money(-7, "USD") };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, fMB1.Negate());
}

///
///
///

///
[Test]
public void BagSimpleAdd()
{
// {[12 CHF][7 USD]} + [14 CHF] == {[26 CHF][7 USD]}
Money[] bag= { new Money(26, "CHF"), new Money(7, "USD") };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, fMB1.Add(f14CHF));
}

///
///
///

///
[Test]
public void BagSubtract()
{
// {[12 CHF][7 USD]} - {[14 CHF][21 USD] == {[-2 CHF][-14 USD]}
Money[] bag= { new Money(-2, "CHF"), new Money(-14, "USD") };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, fMB1.Subtract(fMB2));
}

///
///
///

///
[Test]
public void BagSumAdd()
{
// {[12 CHF][7 USD]} + {[14 CHF][21 USD]} == {[26 CHF][28 USD]}
Money[] bag= { new Money(26, "CHF"), new Money(28, "USD") };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, fMB1.Add(fMB2));
}

///
///
///

///
[Test]
public void IsZero()
{
Assert.IsTrue(fMB1.Subtract(fMB1).IsZero);

Money[] bag = { new Money(0, "CHF"), new Money(0, "USD") };
Assert.IsTrue(new MoneyBag(bag).IsZero);
}

///
///
///

///
[Test]
public void MixedSimpleAdd()
{
// [12 CHF] + [7 USD] == {[12 CHF][7 USD]}
Money[] bag= { f12CHF, f7USD };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, f12CHF.Add(f7USD));
}

///
///
///

///
[Test]
public void MoneyBagEquals()
{
//NOTE: Normally we use Assert.AreEqual to test whether two
// objects are equal. But here we are testing the MoneyBag.Equals()
// method itself, so using AreEqual would not serve the purpose.
Assert.IsFalse(fMB1.Equals(null));

Assert.IsTrue(fMB1.Equals( fMB1 ));
MoneyBag equal= new MoneyBag(new Money(12, "CHF"), new Money(7, "USD"));
Assert.IsTrue(fMB1.Equals(equal));
Assert.IsTrue(!fMB1.Equals(f12CHF));
Assert.IsTrue(!f12CHF.Equals(fMB1));
Assert.IsTrue(!fMB1.Equals(fMB2));
}

///
///
///

///
[Test]
public void MoneyBagHash()
{
MoneyBag equal= new MoneyBag(new Money(12, "CHF"), new Money(7, "USD"));
Assert.AreEqual(fMB1.GetHashCode(), equal.GetHashCode());
}

///
///
///

///
[Test]
public void MoneyEquals()
{
//NOTE: Normally we use Assert.AreEqual to test whether two
// objects are equal. But here we are testing the MoneyBag.Equals()
// method itself, so using AreEqual would not serve the purpose.
Assert.IsFalse(f12CHF.Equals(null));
Money equalMoney= new Money(12, "CHF");
Assert.IsTrue(f12CHF.Equals( f12CHF ));
Assert.IsTrue(f12CHF.Equals( equalMoney ));
Assert.IsFalse(f12CHF.Equals(f14CHF));
}

///
///
///

///
[Test]
public void MoneyHash()
{
Assert.IsFalse(f12CHF.Equals(null));
Money equal= new Money(12, "CHF");
Assert.AreEqual(f12CHF.GetHashCode(), equal.GetHashCode());
}

///
///
///

///
[Test]
public void Normalize()
{
Money[] bag= { new Money(26, "CHF"), new Money(28, "CHF"), new Money(6, "CHF") };
MoneyBag moneyBag= new MoneyBag(bag);
Money[] expected = { new Money(60, "CHF") };
// note: expected is still a MoneyBag
MoneyBag expectedBag= new MoneyBag(expected);
Assert.AreEqual(expectedBag, moneyBag);
}

///
///
///

///
[Test]
public void Normalize2()
{
// {[12 CHF][7 USD]} - [12 CHF] == [7 USD]
Money expected= new Money(7, "USD");
Assert.AreEqual(expected, fMB1.Subtract(f12CHF));
}

///
///
///

///
[Test]
public void Normalize3()
{
// {[12 CHF][7 USD]} - {[12 CHF][3 USD]} == [4 USD]
Money[] s1 = { new Money(12, "CHF"), new Money(3, "USD") };
MoneyBag ms1= new MoneyBag(s1);
Money expected= new Money(4, "USD");
Assert.AreEqual(expected, fMB1.Subtract(ms1));
}

///
///
///

///
[Test]
public void Normalize4()
{
// [12 CHF] - {[12 CHF][3 USD]} == [-3 USD]
Money[] s1 = { new Money(12, "CHF"), new Money(3, "USD") };
MoneyBag ms1= new MoneyBag(s1);
Money expected= new Money(-3, "USD");
Assert.AreEqual(expected, f12CHF.Subtract(ms1));
}

///
///
///

///
[Test]
public void Print()
{
Assert.AreEqual("[12 CHF]", f12CHF.ToString());
}

///
///
///

///
[Test]
public void SimpleAdd()
{
// [12 CHF] + [14 CHF] == [26 CHF]
Money expected= new Money(26, "CHF");
Assert.AreEqual(expected, f12CHF.Add(f14CHF));
}

///
///
///

///
[Test]
public void SimpleBagAdd()
{
// [14 CHF] + {[12 CHF][7 USD]} == {[26 CHF][7 USD]}
Money[] bag= { new Money(26, "CHF"), new Money(7, "USD") };
MoneyBag expected= new MoneyBag(bag);
Assert.AreEqual(expected, f14CHF.Add(fMB1));
}

///
///
///

///
[Test]
public void SimpleMultiply()
{
// [14 CHF] *2 == [28 CHF]
Money expected= new Money(28, "CHF");
Assert.AreEqual(expected, f14CHF.Multiply(2));
}

///
///
///

///
[Test]
public void SimpleNegate()
{
// [14 CHF] negate == [-14 CHF]
Money expected= new Money(-14, "CHF");
Assert.AreEqual(expected, f14CHF.Negate());
}

///
///
///

///
[Test]
public void SimpleSubtract()
{
// [14 CHF] - [12 CHF] == [2 CHF]
Money expected= new Money(2, "CHF");
Assert.AreEqual(expected, f14CHF.Subtract(f12CHF));
}
}
}

Google