www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How does the integrated unittesting work?

reply Berin Loritsch <bloritsch d-haven.org> writes:
It's not easy finding examples that really show you how valid
unit tests are built in D, or how to run them.  I am lacking the
big picture on them.  I see that there is syntax to support the
feature, but beyond that, I am at a loss.

I am used to JUnit, where I have distinct classes, and the test
runner will collect the tests in the classes and execute all the
individual tests.  The results of the tests can then be integrated
with the IDE, presented graphically, or HTML reports made from
them.

The ease of extending JUnit to do what you want is pretty attractive.
However, I am very curious how these things are supposed to work in D.

The fact that D is supposed to have unit test support built in is
a really nice idea.  Since I have been infected by TDD practices,
I want to continue that as I delve into D.

Is there a tutorial, or can someone break it down for me?
Jul 28 2004
next sibling parent Ant <Ant_member pathlink.com> writes:
In article <ce9614$lnv$1 digitaldaemon.com>, Berin Loritsch says...
It's not easy finding examples that really show you how valid
unit tests are built in D, or how to run them.

(warning - all this from memory) unittest are run before main(). as are static this() ctors. remember that when you have a prog that segfaults before the first statement on main() ;) must compile with the flag -unittest. check std.string for examples. Ant
Jul 28 2004
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <ce9614$lnv$1 digitaldaemon.com>, Berin Loritsch says...
Is there a tutorial, or can someone break it down for me?

# // test.d # # int calc( int x, int y ) { return x * y; } # # unittest # { # printf( "Unit tests running\n" ); # assert( calc( 1, 1 ) == 1 ); # assert( calc( 1, 2 ) == 2 ); # assert( calc( 6, 4 ) == 24 ); # } # # int main() { return 0; } From the command line: c:\> dmd -unittest test.d c:\> test Unit tests running c:\> When a program is compiled with the unittest switch, all unit tests will be evaluated when the program is executed. If any of the unit tests fail, you will get an assert error with the line number. If they all succeed then the program will run as normal. The basic idea is that you create a set of tests to verify that your code works. In most cases I try to choose inputs based on knowledge of how the function works so I can test things that might break it. For a fairly involved example, look at format.d in Phobos. Sean
Jul 28 2004
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Sean Kelly wrote:

 In article <ce9614$lnv$1 digitaldaemon.com>, Berin Loritsch says...
 
Is there a tutorial, or can someone break it down for me?

# // test.d # # int calc( int x, int y ) { return x * y; } # # unittest # { # printf( "Unit tests running\n" ); # assert( calc( 1, 1 ) == 1 ); # assert( calc( 1, 2 ) == 2 ); # assert( calc( 6, 4 ) == 24 ); # } # # int main() { return 0; } From the command line: c:\> dmd -unittest test.d c:\> test Unit tests running c:\> When a program is compiled with the unittest switch, all unit tests will be evaluated when the program is executed. If any of the unit tests fail, you will get an assert error with the line number. If they all succeed then the program will run as normal. The basic idea is that you create a set of tests to verify that your code works. In most cases I try to choose inputs based on knowledge of how the function works so I can test things that might break it. For a fairly involved example, look at format.d in Phobos.

This is a bit different than what I would expect... I am used to running unit tests as a function of compilation (i.e. run right after compile), and not before each time I run the software. In a sense, this adds to the perceived startup time of any D program. Asserts are great and all, but what about mock objects? I have found that for methods/functions that pull info or call functions on other objects passed in, the mock object approach works wonders. All I really want to do is test by setting the known value to return from the dependency, or throw an exception from certain methods to ensure the one under test handles the boundary conditions well. I am not clear on how to do that with D--unless we just include a bunch of classes that have no bearing on the application...
Jul 29 2004
parent reply "Walter" <newshound digitalmars.com> writes:
"Berin Loritsch" <bloritsch d-haven.org> wrote in message
news:ceaqrj$1d31$1 digitaldaemon.com...
 I am used to running unit tests as a function of compilation (i.e. run
 right after compile), and not before each time I run the software.

There's no way to run unittests before the software is compiled and linked.
 In a sense, this adds to the perceived startup time of any D program.

Only if you compile with -unittest. Presumably, in a production release, you wouldn't, and the unittests will be left out of the release build.
 Asserts are great and all, but what about mock objects?  I have found
 that for methods/functions that pull info or call functions on other
 objects passed in, the mock object approach works wonders.  All I really
 want to do is test by setting the known value to return from the
 dependency, or throw an exception from certain methods to ensure the
 one under test handles the boundary conditions well.

 I am not clear on how to do that with D--unless we just include a bunch
 of classes that have no bearing on the application...

Why not make a separate module with all the mock classes in it, and not link it in for the release builds?
Jul 29 2004
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Walter wrote:

 "Berin Loritsch" <bloritsch d-haven.org> wrote in message
 news:ceaqrj$1d31$1 digitaldaemon.com...
 
I am used to running unit tests as a function of compilation (i.e. run
right after compile), and not before each time I run the software.

There's no way to run unittests before the software is compiled and linked.

That's common sense. All I was saying is that as soon as the compilation/linking stage is done--that is when I expect the unit tests to be run. Not necessarily when I execute the software.
 
 
In a sense, this adds to the perceived startup time of any D program.

Only if you compile with -unittest. Presumably, in a production release, you wouldn't, and the unittests will be left out of the release build.

Right.
 
 
Asserts are great and all, but what about mock objects?  I have found
that for methods/functions that pull info or call functions on other
objects passed in, the mock object approach works wonders.  All I really
want to do is test by setting the known value to return from the
dependency, or throw an exception from certain methods to ensure the
one under test handles the boundary conditions well.

I am not clear on how to do that with D--unless we just include a bunch
of classes that have no bearing on the application...

Why not make a separate module with all the mock classes in it, and not link it in for the release builds?

:) Ok, I have to figure out how to do that... First things first, though.
Jul 29 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <cebk2v$1n7e$1 digitaldaemon.com>, Berin Loritsch says...
That's common sense.  All I was saying is that as soon as the
compilation/linking stage is done--that is when I expect the unit tests
to be run.  Not necessarily when I execute the software.

In a way, D does even better than your expectations. You don't want the tests to be run when the software is executed; well, DMD distinguishes between a debug build and a release build, and in a release build, the unit tests are not run - and, /even better/, are not even compiled in, so your executable gets smaller. It's easy enough (in a debug build) to get unit tests to run immediately after compilation - just tweak your makefile or build script or whatever you use so that it executes the program after linking. (main() will execute after the unit tests, but you can feed it whatever command line parameters it takes to persuade main to return immediately). Arcane Jill
Jul 29 2004
prev sibling parent Ben Hinkle <bhinkle4 juno.com> writes:
Berin Loritsch wrote:

 It's not easy finding examples that really show you how valid
 unit tests are built in D, or how to run them.  I am lacking the
 big picture on them.  I see that there is syntax to support the
 feature, but beyond that, I am at a loss.
 
 I am used to JUnit, where I have distinct classes, and the test
 runner will collect the tests in the classes and execute all the
 individual tests.  The results of the tests can then be integrated
 with the IDE, presented graphically, or HTML reports made from
 them.
 
 The ease of extending JUnit to do what you want is pretty attractive.
 However, I am very curious how these things are supposed to work in D.
 
 The fact that D is supposed to have unit test support built in is
 a really nice idea.  Since I have been infected by TDD practices,
 I want to continue that as I delve into D.
 
 Is there a tutorial, or can someone break it down for me?

I'd like to add to other replies that the unittest support in D is very simple - all the unit tests get run at startup and the first that fails stops execution. To get fancy stuff like logging, error recovery, test filtering, etc you'd probably have to write a test harness and write your unit tests to interact with the test harness. Or modify the function _moduleUnitTests in src/phobos/std/moduleinit.d to do whatever you want. -Ben
Jul 28 2004