www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - unit-threaded v0.6.13 - tags, autotags and support for integration

reply Atila Neves <atila.neves gmail.com> writes:
Advanced multi-threaded unit testing framework with minimal to no 
boilerplate:

http://code.dlang.org/packages/unit-threaded


What's new:

. Tags.

While selecting which tests to run by package or module is 
definitely handy and mostly what one wants, sometimes there are 
cross-cutting concerns. Now you can tag the tests with whatever 
strings you want and use those strings to filter which tests to 
run:

 Tags("foo", "bar") unittest { /* ... */ }

Running the unittest binary like so:

./ut mypackage  foo ~ baz

Will run every test in mypackage that has the "foo" tag _and_ 
doesn't have the "baz" tag. Adding tags on the command-line can 
only filter, so the number of tests run is always <= of what 
would be run.


. Autotags

Value and type parameterized tests will have tags added to them 
automatically for their value if the  AutoTags UDA is used:

 Values("foo", "bar")  AutoTags unittest { /*...*/ }

The first instantiation will be tagged "foo" and the 2nd "bar".


. Value-parameterized tests can now have more than one  Values 
UDA.

If it does, the unittest block is instantiated with the cartesian 
product of all Values, i.e.

 Values(1, 2, 3)
 Values("foo", "bar")
unittest { /*...*/ }

This produces 6 subtests, one for each combination of the int and 
the string


. Support for integration testing

I've been using unit-threaded for integration testing and added 
something that was very useful to me: a file system sandbox. This 
is especially important when tests are running in threads so they 
don't stomp on each other. The code should be self-explanatory:

with(immutable Sandbox()) {
     writeFile("foo.txt", "foobarbaz\ntoto"); // can also pass 
string[] for lines
     shouldExist("foo.txt");
     shouldNotExist("bar.txt");
     shouldEqualLines("foo.txt", ["foobarbaz", "toto"]);
}

By the default the files get written to and read from 
tmp/unit-threaded/{randomly generated dir name for each test}. 
Notice the lack of / before tmp. That directory can be changed 
with Sandbox.setPath.



. Bug fixes

Enjoy!

Atila
May 16 2016
parent reply Meta <jared771 gmail.com> writes:
On Monday, 16 May 2016 at 08:37:48 UTC, Atila Neves wrote:
 with(immutable Sandbox()) {
     writeFile("foo.txt", "foobarbaz\ntoto"); // can also pass 
 string[] for lines
     shouldExist("foo.txt");
     shouldNotExist("bar.txt");
     shouldEqualLines("foo.txt", ["foobarbaz", "toto"]);
 }
That's a really neat trick and an interesting use of `with`. I remember that variables initialized in the argument list of `with` used to not be destroyed after exiting the scope, I'm guessing that's not the case anymore? I vaguely remember a PR that fixed that. Anyway, congratulations on the new release!
May 16 2016
parent reply Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Monday, 16 May 2016 at 14:39:22 UTC, Meta wrote:
 On Monday, 16 May 2016 at 08:37:48 UTC, Atila Neves wrote:
 with(immutable Sandbox()) {
     writeFile("foo.txt", "foobarbaz\ntoto"); // can also pass 
 string[] for lines
     shouldExist("foo.txt");
     shouldNotExist("bar.txt");
     shouldEqualLines("foo.txt", ["foobarbaz", "toto"]);
 }
That's a really neat trick and an interesting use of `with`. I remember that variables initialized in the argument list of `with` used to not be destroyed after exiting the scope, I'm guessing that's not the case anymore? I vaguely remember a PR that fixed that.
You surely mean "used to be destroy", right? Yes, that's been fixed.
 Anyway, congratulations on the new release!
May 17 2016
parent reply Meta <jared771 gmail.com> writes:
On Tuesday, 17 May 2016 at 09:54:15 UTC, Marc Schütz wrote:
 You surely mean "used to be destroy", right?
Good question... If I write this: struct Test { ~this() { writeln("destroying Test"); } } with (Test()) { //Do stuff } Will Test's destructor be run once we exit the `with` scope?
May 17 2016
next sibling parent Atila Neves <atila.neves gmail.com> writes:
On Tuesday, 17 May 2016 at 14:22:51 UTC, Meta wrote:
 On Tuesday, 17 May 2016 at 09:54:15 UTC, Marc Schütz wrote:
 You surely mean "used to be destroy", right?
Good question... If I write this: struct Test { ~this() { writeln("destroying Test"); } } with (Test()) { //Do stuff } Will Test's destructor be run once we exit the `with` scope?
It did for me on the latest release. Atila
May 17 2016
prev sibling next sibling parent Marc =?UTF-8?B?U2Now7x0eg==?= <schuetzm gmx.net> writes:
On Tuesday, 17 May 2016 at 14:22:51 UTC, Meta wrote:
 On Tuesday, 17 May 2016 at 09:54:15 UTC, Marc Schütz wrote:
 You surely mean "used to be destroy", right?
Good question... If I write this: struct Test { ~this() { writeln("destroying Test"); } } with (Test()) { //Do stuff } Will Test's destructor be run once we exit the `with` scope?
Yes, it was fixed almost two years ago: https://github.com/dlang/dmd/pull/3855
May 17 2016
prev sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 05/17/2016 10:22 AM, Meta wrote:
 On Tuesday, 17 May 2016 at 09:54:15 UTC, Marc Schütz wrote:
 You surely mean "used to be destroy", right?
Good question... If I write this: struct Test { ~this() { writeln("destroying Test"); } } with (Test()) { //Do stuff } Will Test's destructor be run once we exit the `with` scope?
Should.
May 17 2016