www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - UnitTest and visual D

reply "Chris Pons" <cmpons gmail.com> writes:
I am following the book "The D Programming Language" and am at 
the portion about functions and unittest. For some reason I 
cannot get unittest to do anything noticeable.

I right clicked on my Project > Properties > Command Line and 
under additional options added -unittest (--main gave me an error 
saying unrecognized switch). After I compiled the code, the 
program ran as normal. Am I missing something? This is what I 
have so far:

int[]find(int[] haystack, int needle)
{
	while(haystack.length > 0 && haystack[0] != needle){
		haystack = haystack[1 .. $];
	}
	return haystack;	
}

unittest
{
	int[] a = [];
	assert(find(a, 5) == []);
	a = [ 1, 2, 3 ];
	assert(find(a, 0) == []);
	assert(find(a, 1).length == 3);
	assert(find(a, 2).length == 2);
	assert(a[0 $ - find(a, 3).length] [ 1, 2 ]);
}

void main()
{
	int[3] array = [3, 4, 5];
	int needle = 4;

	find(array, needle);
}
Feb 23 2012
next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, February 24, 2012 02:11:50 Chris Pons wrote:
 I am following the book "The D Programming Language" and am at
 the portion about functions and unittest. For some reason I
 cannot get unittest to do anything noticeable.

If the unit tests pass, they don't print anything unless you add statements to them which do. You only get stuff being printed out on failure. This works particularly well for the command line (it's normal in Unix-land for stuff to print nothing on success unless them printing stuff out is their job - this makes it easier to pipe programs and the like). Some people complain about it from time to time, but that's the way it is. If you really want them to print something though, you can always add your own print statements. If you compiled with -unittest, the unit tests run before main does, so if all of your tests pass, then your program will run normally after the unit tests have been run. It's not uncommon for people to do something like this so that they can have the unit tests run without running their actual program: version(unittest) void main() {} else void main() { //Your normal main... } - Jonathan M Davis
Feb 23 2012
prev sibling next sibling parent "Chris Pons" <cmpons gmail.com> writes:
Ok, thanks.

I haven't run into version(...) yet. Would I be correct if I 
assumed that this version of void main: void main() {} would only 
run if -unittest was in the command line?

Also, what should be in a unit test? Test cases to make sure 
certain functions/classes are working as you intend them to?


 If the unit tests pass, they don't print anything unless you 
 add statements to
 them which do. You only get stuff being printed out on failure. 
 This works
 particularly well for the command line (it's normal in 
 Unix-land for stuff to
 print nothing on success unless them printing stuff out is 
 their job - this
 makes it easier to pipe programs and the like). Some people 
 complain about it
 from time to time, but that's the way it is. If you really want 
 them to print
 something though, you can always add your own print statements.

 If you compiled with -unittest, the unit tests run before main 
 does, so if all
 of your tests pass, then your program will run normally after 
 the unit tests
 have been run.

 It's not uncommon for people to do something like this so that 
 they can have
 the unit tests run without running their actual program:

 version(unittest) void main() {}
 else void main()
 {
  //Your normal main...
 }

 - Jonathan M Davis

Feb 23 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, February 24, 2012 03:12:08 Chris Pons wrote:
 Ok, thanks.
 
 I haven't run into version(...) yet. Would I be correct if I
 assumed that this version of void main: void main() {} would only
 run if -unittest was in the command line?

Yes. version(symbol) means that anything within that block is compiled in if the version symbol has been defined (either in code or via the command-line). For instance, version(Posix) {} else version(Windows) {} else static assert("Unsupported OS"); would give you three different versions of the code. The Posix one gets compiled in on Posix systems. The Windows one gets compiled in on Windows systems, and the third block gets compiled in on everything else (in this case, with a static assertion so that you get an error when you try and compile with an unsupported OS). The version unittest is enabled when you compile with -unittest, so anything in version(unittest) gets compiled in.
 Also, what should be in a unit test? Test cases to make sure
 certain functions/classes are working as you intend them to?

Yes. Typically, after every function you put a unittest block with assertions that verify that that function is working correctly. And unit tests which tests combinations of functions can be useful as well. But regardless, the idea is to use unit tests to verify that your code works how it's supposed to and fails how it's supposed to (e.g. when certain input should result in an exception being thrown) so that you know not only that your code works currently but that your code continues to work when you make changes to it in the future. It makes for much more robust code and often actually increases the speed of development, because you end up with fewer bugs (since you catch them when you write the tests, which you typically do when you write the code). - Jonathan M Davis
Feb 23 2012
prev sibling next sibling parent Kevin Cox <kevincox.ca gmail.com> writes:
--0015175ce042c74ca304b9aca86c
Content-Type: text/plain; charset=UTF-8

I am having the same problem with visual d plugin for monodevelop.  When I
compile from the command line the tests run.

A possibly related problem is that some files do not get recompiled when
changed unless I do a rebuild.
On Feb 23, 2012 8:38 PM, "Jonathan M Davis" <jmdavisProg gmx.com> wrote:

 On Friday, February 24, 2012 02:11:50 Chris Pons wrote:
 I am following the book "The D Programming Language" and am at
 the portion about functions and unittest. For some reason I
 cannot get unittest to do anything noticeable.

If the unit tests pass, they don't print anything unless you add statements to them which do. You only get stuff being printed out on failure. This works particularly well for the command line (it's normal in Unix-land for stuff to print nothing on success unless them printing stuff out is their job - this makes it easier to pipe programs and the like). Some people complain about it from time to time, but that's the way it is. If you really want them to print something though, you can always add your own print statements. If you compiled with -unittest, the unit tests run before main does, so if all of your tests pass, then your program will run normally after the unit tests have been run. It's not uncommon for people to do something like this so that they can have the unit tests run without running their actual program: version(unittest) void main() {} else void main() { //Your normal main... } - Jonathan M Davis

--0015175ce042c74ca304b9aca86c Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <p>I am having the same problem with visual d plugin for monodevelop.=C2=A0= When I compile from the command line the tests run.</p> <p>A possibly related problem is that some files do not get recompiled when= changed unless I do a rebuild.</p> <div class=3D"gmail_quote">On Feb 23, 2012 8:38 PM, &quot;Jonathan M Davis&= quot; &lt;<a href=3D"mailto:jmdavisProg gmx.com">jmdavisProg gmx.com</a>&gt= ; wrote:<br type=3D"attribution"><blockquote class=3D"gmail_quote" style=3D= "margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> On Friday, February 24, 2012 02:11:50 Chris Pons wrote:<br> &gt; I am following the book &quot;The D Programming Language&quot; and am = at<br> &gt; the portion about functions and unittest. For some reason I<br> &gt; cannot get unittest to do anything noticeable.<br> <br> If the unit tests pass, they don&#39;t print anything unless you add statem= ents to<br> them which do. You only get stuff being printed out on failure. This works<= br> particularly well for the command line (it&#39;s normal in Unix-land for st= uff to<br> print nothing on success unless them printing stuff out is their job - this= <br> makes it easier to pipe programs and the like). Some people complain about = it<br> from time to time, but that&#39;s the way it is. If you really want them to= print<br> something though, you can always add your own print statements.<br> <br> If you compiled with -unittest, the unit tests run before main does, so if = all<br> of your tests pass, then your program will run normally after the unit test= s<br> have been run.<br> <br> It&#39;s not uncommon for people to do something like this so that they can= have<br> the unit tests run without running their actual program:<br> <br> version(unittest) void main() {}<br> else void main()<br> {<br> =C2=A0//Your normal main...<br> }<br> <br> - Jonathan M Davis<br> </blockquote></div> --0015175ce042c74ca304b9aca86c--
Feb 23 2012
prev sibling next sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, February 23, 2012 21:38:43 Kevin Cox wrote:
 I am having the same problem with visual d plugin for monodevelop. When I
 compile from the command line the tests run.
 
 A possibly related problem is that some files do not get recompiled when
 changed unless I do a rebuild.

There may very well be further problems due to what the IDE is doing (such as not doing a full recompile when you enable -unittest), but the unit tests won't print anything out on success regardless unless you use print statements in them. - Jonathan M Davis
Feb 23 2012
prev sibling next sibling parent Kevin Cox <kevincox.ca gmail.com> writes:
--0015175ce042e8fe4a04b9acc73d
Content-Type: text/plain; charset=UTF-8

On Feb 23, 2012 9:41 PM, "Jonathan M Davis" <jmdavisProg gmx.com> wrote
 There may very well be further problems due to what the IDE is doing

 not doing a full recompile when you enable -unittest), but the unit tests
 won't print anything out on success regardless unless you use print

 in them

It still doesn't run them when I do a full rebuild. In the build output I see -unittest in the command line. It is really weird. I haven't looked at it too closly. For now I am just compiling from the command line. --0015175ce042e8fe4a04b9acc73d Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <p><br> On Feb 23, 2012 9:41 PM, &quot;Jonathan M Davis&quot; &lt;<a href=3D"mailto= :jmdavisProg gmx.com">jmdavisProg gmx.com</a>&gt; wrote<br> &gt; There may very well be further problems due to what the IDE is doing (= such as<br> &gt; not doing a full recompile when you enable -unittest), but the unit te= sts<br> &gt; won&#39;t print anything out on success regardless unless you use prin= t statements<br> &gt; in them</p> <p>It still doesn&#39;t run them when I do a full rebuild.=C2=A0 In the bui= ld output I see -unittest in the command line.=C2=A0 It is really weird.=C2= =A0 I haven&#39;t looked at it too closly.=C2=A0 For now I am just compilin= g from the command line.</p> --0015175ce042e8fe4a04b9acc73d--
Feb 23 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Thursday, February 23, 2012 21:47:26 Kevin Cox wrote:
 It still doesn't run them when I do a full rebuild.  In the build output I
 see -unittest in the command line.  It is really weird.  I haven't looked
 at it too closly.  For now I am just compiling from the command line.

Well, I'm afraid that I've never used an IDE with D, so I can't really help with IDE-specific problems. It does sound like your not running the right binary though (like maybe you ended up with two of them, and it's the old one which is being run). I can only guess though. - Jonathan M Davis
Feb 23 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Feb 23, 2012 at 09:28:07PM -0500, Jonathan M Davis wrote:
 On Friday, February 24, 2012 03:12:08 Chris Pons wrote:

 Also, what should be in a unit test? Test cases to make sure
 certain functions/classes are working as you intend them to?


Pretty much. The idea is to put stuff in there to check that your code actually does what you think it does. Especially useful are tests that check boundary conditions (i.e., corner cases, like empty input, input which is 0, off-by-1 input, null input). [...]
 But regardless, the idea is to use unit tests to verify that your code
 works how it's supposed to and fails how it's supposed to (e.g. when
 certain input should result in an exception being thrown)

For which the assertThrown template is very useful: unittest { // Instantiate an object of the class you're writing auto o = new myClass; // Make sure an exception is thrown when you try to do // something illegal. assertThrown!Exception(o.parse(illegalInput)); } The template basically runs o.parse(...), and if it throws an Exception, then it catches it and continues running the unittest. However, if o.parse(...) returns without throwing an Exception, then the template will throw a unit test failure exception.
 so that you know not only that your code works currently but that your
 code continues to work when you make changes to it in the future.

This is one of the big benefits of unittests. By putting in test cases that ensure your code does what you think it does, when you make a change in the future the same test cases will tell you if you also broke a previously working feature.
 It makes for much more robust code and often actually increases the
 speed of development, because you end up with fewer bugs (since you
 catch them when you write the tests, which you typically do when you
 write the code).

One thing I absolutely love about D unittests is that they're so dang easy to write that you really have no excuse not to write them. Which is the point, because most programmers in principle agree that unittests are good, but they don't actually write them because traditionally (1) unittests are external to the code you're writing, so there's the effort of putting your current code on hold, switching to a different directory, and adding a unittest there, then switch back. (2) They're often in a different language, like Python or Expect, and it's mentally taxing to keep switching back and forth between languages in the middle of your coding session. (3) They have to be run separately, which most programmers are too lazy to do. All of these, together with tight deadlines, often result in no unittests or outdated unittests. In D, by building unittests into the language and allowing unittest blocks pretty much anywhere in the code (except inside a function), as soon as you think of a corner case the complex algorithm you're writing might want to handle, you can just stick it in the unittest block next to the function and keep going. Often I find that before I even finish writing a function, I've already written 2-3 unittests for it, and after I finish it, I add a few more. By the time I actually run the program, the new code already has a stringent set of tests that will quickly catch any obvious bugs. Then if your tests missed some test case that you later discover to cause a bug, you just add it to the growing list of unittest blocks, and then any further changes after that will always run that new test, ensuring that the bug will never come back again. D's unittests also never stagnate and get outdated: once you compile with -unittest, your program will refuse to run until you fix the bug that caused unittest failure. It's good motivation to actually fix the bug instead of saying "I'll do it later", which often means "it won't get done 'cos I'll forget by then". T -- "Uhh, I'm still not here." -- KD, while "away" on ICQ.
Feb 23 2012
prev sibling next sibling parent "Chris Pons" <cmpons gmail.com> writes:
Thanks for the response. There are a lot of great features to D 
that really excites me about using this language. Unittest is 
definitely one of them.

It's hard for me to imagine myself going back to C++ at this 
point because of the amount of great features in D. :)
Feb 23 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Feb 24, 2012 at 05:17:27AM +0100, Chris Pons wrote:
[...]
 It's hard for me to imagine myself going back to C++ at this point
 because of the amount of great features in D. :)

Yeah I starting using D recently, and now I just can't convince myself to start another C/C++ project. It's just maintenance now, until I port my projects to D. :P T -- Life would be easier if I had the source code. -- YHL
Feb 23 2012