logo       

design issue: msg#00181

java.junit.user

Subject: design issue

Can somebody suggest on some issue of JUnit API usage
or test case design? Sorry for a long appendix code.
The essence is that I want to start some application
once in VM session and run all my test methods
afterwards. I could not find sufficient place to put
my initial call
ClientMain.main (null);
First I tried setUp(), but it is called before every
test method. Then I tried to implement TestListener to
use startTest() method. It in turn was not obvious,
and you can see the indirect tricks I had to use with
run() method and result class, please suggest me
easier way. But anyways it did not help as startTest()
was also called before every test method (what is the
difference?) Then I finally used static counters.
Please suggest me proper solution.





------------------------------------------------------------
package com.imc.testutil;

// log4j
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.Logger;
// junit
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestResult;
import junit.framework.AssertionFailedError;
import junit.framework.TestListener;


/**
This is intended wrapper for all imc test cases.
<p>
Here we
<ol>
<li>configure logger from properties file
<li>add TestListener
<li>count test method calls
<li>distinguish first test method call for child to
put all settings called once per suite
<li>do some dummy loggings of method calls
</ol>
</p>
<p>
We experience the following design difficulties,
deriving either from JUnit API imperfection
or our poor usage of the latter, namely:
<ol>
<li>It was not obvious how to add TestListener.
Then we needed to overwrite run() method which does
not seem proper way.
<li>The listener being added, we discover startTest()
method to have unexpected functionality.
We need the place to put code called once per suite.
Instead, startTest() is called before every testXXX()
method just like setUp()
Then what is the difference?
Likewise we could use setUp(), statically counting
calls
and implement firstSetUp().
</ol>
@since on 10 June 2002
@author Boris Garbuzov
*/
public class ImcTestCase
extends TestCase
// second listener after TestRunner in the JVM
process
implements TestListener
{

/*
We can use log befoe or in first constructor.
*/
static
{
PropertyConfigurator.configure("log4j.properties");
}

/** this flag is static because testrunner create
new instance of
* of this class for every testXXX method. This
flag is needed to fire
* method firstStartTest() only one time. This
method is famous for operations
* that needs only one time. Look at method
run(TestResult ..)
@deprecated. currentStartTestIndex is used instead
*/
//private static boolean isStartTestFirst = false;

/**
generalizes the idea of isStartTestFirst
checked and incremented in startTest()
and published in getCurrentStartTestIndex
It is good to police the usage
so that this variable could be only incremented, and
not voluntarily reset.
*/
private static int currentStartTestIndex = 0;

/**
JUnit after TestRunner calls this constructor
with name = testXxxx - the current test method
*/
public ImcTestCase (String name)
{
super(name);
//createResult().addListener (this); // does not
help
getDefaultLogger().info("instance created with name
= " + name);
}

/**
Extension Test code calls this method for casual
logging needs.
This should not add much overhead.
Logger does quick lookup by name.
That is why we get rid of the field.
*/
protected Logger getDefaultLogger()
{
return Logger.getLogger (getName());
}

/**
* Overide
* Runs the test case and collects the results in
TestResult.
* And adds this class as TestListener
Is it the only way?
May be "createResult().addListener (this)" whould
suffice?
*/
public void run(TestResult result)
{
result.addListener(this);
super.run (result);
}

/** implements startTest interface method
children can add here call of original application to
be tested
For the child class it is desirable to call this
super first
in case of overwriting to prevent obuse.
*/
public void startTest(Test test)
{
getDefaultLogger().info("Start test " + getName());
currentStartTestIndex++;
// moved from run()
if(currentStartTestIndex == 1)
{
firstStartTest();
}
}

/** implements addFailure interface method
*/
public void addFailure(Test test,
AssertionFailedError assertionFailedError)
{
getDefaultLogger().error(
assertionFailedError.getMessage() );
}

/** implements endTest interface method
*/
public void endTest(Test test)
{
getDefaultLogger().info("Finish test " + getName());
}

/** implements TestLister
Here we just log the fact of invokation and print the
error.
The children can overwrite it adding sensible stuff.
*/
public void addError(Test test, Throwable
throwable)
{
getDefaultLogger().error(throwable.getMessage());
}

/**
@since June 2002 for children to override it
calling original application once per suite
The child should not necessarily call this super,
but it does not hurt too.
*/
public void firstStartTest()
{
getDefaultLogger().info ("\r\n
IncTestCase.firstStartTest() is called \r\n");
}

/**
publishes current index of test method running
*/
public int getCurrentStartTestIndex()
{
return currentStartTestIndex;
}
}





-------------------------------------------------------
package com.imc.mymailloop.demo.boris2.test4;

// jdk
import javax.swing.JFrame;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.Color;
// junit
import com.imc.testutil.TestChartView;
import com.imc.testutil.ImcTestCase;
import junit.framework.Test;
// jemmy
import org.netbeans.jemmy.operators.JDialogOperator;
import
org.netbeans.jemmy.operators.AbstractButtonOperator;
import org.netbeans.jemmy.operators.JFrameOperator;
import org.netbeans.jemmy.operators.JMenuBarOperator;
// log4j
import org.apache.log4j.Logger;
// ours
import com.imc.mymailloop.demo.boris2.ClientMain;

/**

*/
public class AppTest
extends ImcTestCase
{
// this is timeout betwean test operations
private static int SHOW_TIMEOUT = 2000;

/**
defined first and then used in test methods
*/
private JFrameOperator jframeMain = null;

/** Creates new AppTest */
public AppTest(String name)
{
super(name);
}

/**
overrides JUnit's default
called before every test method
2 times in our case
*/
public void setUp()
throws Exception
{
// gets main frame
jframeMain = new JFrameOperator("Try it");
}

/**
overwrites super's
Put here call of initial app instead of RunTests
*/
public void firstStartTest()
{
super.firstStartTest(); // just for logging
// otherwise we can put this to static area.
ClientMain.main (null);
}

/**
first test method
<ol>
<li>It finds Help|About menu,
<li>Pusles it,
<li>Finds About dialog
<li>Finds OK button on it
<li>Pushes it.
<li>Does sofisticated logging on the way.
</ol>
*/
public void testMenu()
{
// stuff
}


}


__________________________________________________
Do You Yahoo!?
Yahoo! - Official partner of 2002 FIFA World Cup
http://fifaworldcup.yahoo.com




<Prev in Thread] Current Thread [Next in Thread>
Google Custom Search

News | FAQ | advertise