Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > state of an object in setUp() of junit TestCase

Reply
Thread Tools

state of an object in setUp() of junit TestCase

 
 
jimgardener
Guest
Posts: n/a
 
      10-30-2010
If I forget to define a tearDown() method ,will an object initialized
in setUp() maintain its state in between two test methods?
suppose I am testing a Stopwatch class
<code>
public class Stopwatch {
public long startTime=0;
public long stopTime=0;
boolean isrunning=false;
public void start(){
startTime=System.currentTimeMillis();
isrunning=true;
}
public void stop(){
if (isrunning) stopTime=System.currentTimeMillis();
isrunning=false;
}

public long getTotalDurationMilliSeconds(){
long duration=0;
if( isrunning){
duration=(System.currentTimeMillis()-startTime);
}
else{
duration=stopTime-startTime;
}
return duration;
}
public void reset(){
startTime=0;
stopTime=0;
isrunning=false;
}

public long getTotalDurationSeconds(){
long duration=0;
if( isrunning){
duration=((System.currentTimeMillis()-startTime)/1000);
}
else{
duration=(stopTime-startTime)/1000;
}
return duration;
}
}

</code>

I have a testcase like below,in which I have a setUp() but no
tearDown()


<code>
class StopwatchTest extends TestCase{
private Stopwatch watch;
public StopwatchTest(String name){
super(name);
}
public void setUp(){
watch=new Stopwatch();
}
private void sleepForSomeTime(long timeinmillisecs){
try{
System.out.println("sleeping for :"+(timeinmillisecs/1000)+"secs");
Thread.sleep(timeinmillisecs);
}catch(InterruptedException e){

}
}
public void testNormalOpButForgottToStop(){
watch.start();
sleepForSomeTime(3000);
//watch is not stopped;
assertEquals(3,watch.getTotalDurationSeconds());
}
public void testStoppedBeforeStart(){
System.out.println("timeduration:"+watch.getTotalD urationSeconds());
sleepForSomeTime(2000);
watch.stop();
System.out.println("timeduration:"+watch.getTotalD urationSeconds());
assertEquals(0,watch.getTotalDurationSeconds());
}

}

</code>

It seems that the watch is initialized each time before running the
test methods.Is this the expected behaviour?


regards,
jim

 
Reply With Quote
 
 
 
 
jimgardener
Guest
Posts: n/a
 
      10-30-2010

> It seems that the watch is initialized each time before running the
> test methods.Is this the expected behaviour?



sorry..wrong wording..looks like the state of the object is reset each
time before the test method
jim
 
Reply With Quote
 
 
 
 
Lew
Guest
Posts: n/a
 
      10-30-2010
You answered your own question, so I will just address some side issues.

jimgardener wrote:
> If I forget to define a tearDown() method ,will an object initialized
> in setUp() maintain its state in between two test methods?
> suppose I am testing a Stopwatch class
> <code>
> public class Stopwatch {
> public long startTime=0;


These are the default values. Explicitly setting them in member
initialization causes them to be set twice. In the case of 'startTime' and
'isrunning' [sic] you don't even use the initial value, so why bother setting it?

> public long stopTime=0;
> boolean isrunning=false;


The variable name 'isrunning' violates the naming conventions.

> public void start(){
> startTime=System.currentTimeMillis();
> isrunning=true;
> }
> public void stop(){
> if (isrunning) stopTime=System.currentTimeMillis();


This 'if' block violates the coding conventions.

> isrunning=false;
> }
>
> public long getTotalDurationMilliSeconds(){
> long duration=0;


You never use the '0' value, so why do you set it? Just so you can discard it?

> if( isrunning){
> duration=(System.currentTimeMillis()-startTime);
> }
> else{
> duration=stopTime-startTime;
> }
> return duration;
> }
> public void reset(){
> startTime=0;
> stopTime=0;
> isrunning=false;
> }
>
> public long getTotalDurationSeconds(){
> long duration=0;


Again, why did you initialize 'duration' to a value that is immediately discarded?

> if( isrunning){
> duration=((System.currentTimeMillis()-startTime)/1000);
> }
> else{
> duration=(stopTime-startTime)/1000;
> }
> return duration;
> }
> }
>
> </code>
>
> I have a testcase like below,in which I have a setUp() but no
> tearDown()
>
>
> <code>
> class StopwatchTest extends TestCase{


How come you aren't using '@Test'?

> private Stopwatch watch;
> public StopwatchTest(String name){
> super(name);
> }
> public void setUp(){
> watch=new Stopwatch();
> }
> private void sleepForSomeTime(long timeinmillisecs){


The variable name 'timeinmillisecs' egregiously violates the naming standards.

> try{
> System.out.println("sleeping for :"+(timeinmillisecs/1000)+"secs");


'System.out.println()'? Really? Come on.

If it's important enough to log, it's important enough to log correctly.

If you really are such a schlemiel that you have to use a
'System.X.println()', use 'System.err' at least. But really, use a logger.

> Thread.sleep(timeinmillisecs);
> }catch(InterruptedException e){
>
> }
> }
> public void testNormalOpButForgottToStop(){
> watch.start();
> sleepForSomeTime(3000);
> //watch is not stopped;
> assertEquals(3,watch.getTotalDurationSeconds());
> }


This is not a valid test. Since the watch is not stopped and sleep times are
approximate, you have a small risk that this assertion will fail even with
correct code.

The granularity of one second will make this rare, but not theoretically
impossible. You should comment your code that you depend on the granularity
to avoid trouble.

> public void testStoppedBeforeStart(){
> System.out.println("timeduration:"+watch.getTotalD urationSeconds());
> sleepForSomeTime(2000);
> watch.stop();
> System.out.println("timeduration:"+watch.getTotalD urationSeconds());
> assertEquals(0,watch.getTotalDurationSeconds());
> }
>
> }
>
> </code>
>
> It seems that the watch is initialized each time before running the
> test methods.Is this the expected behaviour?


--
Lew
 
Reply With Quote
 
jimgardener
Guest
Posts: n/a
 
      10-30-2010
sorry..that was sloppy work on my side..Will be more careful..
thanks Lew for the suggestions.
regards
jim

 
Reply With Quote
 
Tom Anderson
Guest
Posts: n/a
 
      10-30-2010
On Sat, 30 Oct 2010, jimgardener wrote:

> If I forget to define a tearDown() method ,will an object initialized
> in setUp() maintain its state in between two test methods?


No. JUnit creates a new instance of the test class for each test; if you
write your test classes as you do (which is the right way to do it), then
state won't leak from one test to the next, because there's a fresh set of
instance variables each time.

Note the if - if, on the other hand, you keep state in places which
persist between instances (static variables, objects outside the test
object), then it will leak from test to test. So don't do that.

tom

--
Ed editor textorum probatissimus est -- Cicero, De officiis IV.7
 
Reply With Quote
 
Stanimir Stamenkov
Guest
Posts: n/a
 
      10-30-2010
Sat, 30 Oct 2010 10:55:22 -0400, /Lew/:
> jimgardener wrote:
>
>> public class Stopwatch {
>> public long startTime=0;

>
> These are the default values. Explicitly setting them in member
> initialization causes them to be set twice.


I don't like specifying initializers using the default values for
the same reason, but I was once pointed to the Java Tutorial
<http://download.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html>
(see the "Default Values" section):

> ... Relying on such default values, however, is generally
> considered bad programming style.


I don't completely agree with the given statement, but then I can't
come up with arguments on any side. What do you think about it?

--
Stanimir
 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      10-30-2010
On 10/30/2010 9:39 AM, Stanimir Stamenkov wrote:

>> ... Relying on such default values, however, is generally
>> considered bad programming style.

>
> I don't completely agree with the given statement, but then I can't come
> up with arguments on any side. What do you think about it?



Lew's comment that an explicit initialization requires a second,
redundant and useless initialization is enough to counter Oracle's
statement.

I'd say precisely the opposite. The default values are 100% guaranteed
and deterministic, there's no reason not to rely on them, and it's
certainly not bad style. I'm sorry for whoever wrote that line in the
tutorial but I think they went off some place unknown to most professionals.


 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      10-30-2010
On 10/30/2010 9:24 AM, Tom Anderson wrote:

> Note the if - if, on the other hand, you keep state in places which
> persist between instances (static variables, objects outside the test
> object), then it will leak from test to test. So don't do that.



I've used instance fields but initialized them each time before a test.
I don't know if this is good practice or not but there it is.

Partial code:


public class BasicIrcParserTest
{

private Writer writer;
private MockCommandList commandList;
private ChatScreen screen;

@Before
public void setUp()
{
writer = new StringWriter();
commandList = new MockCommandList();
screen = new ChatScreen()
...
}

....

 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      10-30-2010
On 10/30/2010 12:45 PM, markspace wrote:
> On 10/30/2010 9:39 AM, Stanimir Stamenkov wrote:
>
>>> ... Relying on such default values, however, is generally
>>> considered bad programming style.

>>
>> I don't completely agree with the given statement, but then I can't come
>> up with arguments on any side. What do you think about it?


> Lew's comment that an explicit initialization requires a second,
> redundant and useless initialization is enough to counter Oracle's
> statement.
>
> I'd say precisely the opposite. The default values are 100% guaranteed
> and deterministic, there's no reason not to rely on them, and it's
> certainly not bad style. I'm sorry for whoever wrote that line in the
> tutorial but I think they went off some place unknown to most
> professionals.


This is a controversy. I sit somewhat in the middle - if the default initial
value carries algorithmic significance, e.g.,

private boolean initialized = false;

then the redundant initialization emphasizes that the algorithm depends on
that value, but if the usage pattern requires a call to some 'init()' or
'setup()' or 'prepare()' or such that sets the value before it's read, or if
otherwise there's nothing truly emphatic about the default value, then one
should follow markspace's advice.

private boolean initialized;

IME a need to emphasize initialization of member references to 'null' is rarer
than a need to emphasize initialization of primitives to their "zero-like" values.

Mind you, it is still completely unnecessary to initialize a member twice to
its default value just to make a point that a comment would make just as well,

private boolean initialized; // must start out 'false'

perhaps augmented with an invariant if you're anal retentive.

/** Constructor. */
public Foo()
{
// ... do all those lovely constructor things
assert ! initialized;
}

Now that makes the point and the JVM can help enforce it.

--
Lew
Anal expressive: like anal retentive but beneficially.
The anal expressive personality pays close attention to detail but is relaxed
about it.
 
Reply With Quote
 
Lew
Guest
Posts: n/a
 
      10-30-2010
markspace wrote:
> I've used instance fields but initialized them each time before a test.
> I don't know if this is good practice or not but there it is.
>
> Partial code:
>
> public class BasicIrcParserTest
> {
>
> private Writer writer;
> private MockCommandList commandList;
> private ChatScreen screen;
>
> @Before
> public void setUp()
> {
> writer = new StringWriter();
> commandList = new MockCommandList();
> screen = new ChatScreen()
> ...
> }
>
> ...


I aver that that is good practice. First, the default value for 'writer' will
be 'null', so you need to initialize to the non-default values in your
'@Before'. So you have no choice. Second, you aren't leaving it undocumented
to those who read your test source - maintainers can readily follow the test
flow. Third, you provide a hook for future initializations as the test class
expands.

--
Lew
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Differerence between Test::Unit::TestCase and RUNIT::TestCase Scott Ruby 1 08-20-2005 08:49 PM
unittest.TestCase, lambda and __getitem__ Steven Bethard Python 7 09-14-2004 02:43 PM
Create TestCase with WSAD on EJB Memi Lavi Java 0 08-05-2004 03:23 PM
Computing test methods in unittest.TestCase Jan Decaluwe Python 2 03-02-2004 06:33 PM
standard struts testcase failed ? Charlie Java 1 10-16-2003 04:58 AM



Advertisments