Jump to page: 1 2
Thread overview
selectively running unittest functions
Oct 25, 2013
Daniel Davidson
Oct 25, 2013
Dicebot
Oct 25, 2013
Daniel Davidson
Oct 25, 2013
Dicebot
Oct 25, 2013
Dicebot
Oct 25, 2013
Daniel Davidson
Oct 25, 2013
Dicebot
Oct 25, 2013
simendsjo
Oct 25, 2013
Daniel Davidson
Oct 25, 2013
Daniel Davidson
Oct 26, 2013
Dmitry Olshansky
Oct 26, 2013
Daniel Davidson
Oct 25, 2013
Gary Willoughby
Oct 25, 2013
Gary Willoughby
Oct 25, 2013
Dicebot
Oct 26, 2013
Daniel Davidson
October 25, 2013
I've been through this thread: http://forum.dlang.org/post/mailman.1454.1369104411.4724.digitalmars-d@puremagic.com

I would like the named unittests, as describe there, but I don't think it is in the works (if I'm wrong please let me know). So I took an approach outlined here (http://www.reddit.com/r/programming/comments/1edih2/dconf_2013_day_1_talk_4_writing_testable_code_in/c9zg3ry) and created a minimal, simple scheme.

The support file is here: http://pastebin.com/tU9BuS3G

To use it:
- import the support file
- mixin an init routine `mixin UTInit!__MODULE__;` to your module
- Instead of using unittest blocks (or in addition) put code in annotated functions.
   `@UT void testFoo() { .... }


To run all tests:
  `rdmd -version=UT --main program`
To filter by module (using regex)
   `rdmd -version=UT --main program -m 'foo.*'`
To filter by test function (using regex)
   `rdmd -version=UT --main program -t 'foo.*'`

I think the approach makes sense, but I am looking any comments/criticisms on what may be missing or misguided.

The downsides as I see it:
- it is not standard
- it comes with a version, UT. So you can/should wrap all tests in version(UT) to ensure they never make it to production
- all test functions must be at module level. Not sure if there are any ramifications?

The pluses:
- filtering of test by module and function name
- it works along side of unittest. It can also work with others like specd which is a nice way to describe tests and know when things fail the location.


Thanks
Dan
October 25, 2013
I strictly believe any unittest enhancing library must be built on top of existing unittest blocks using __traits(getUnittest) and be 100% compatible with normal `-unittest` mode
October 25, 2013
On Friday, 25 October 2013 at 13:04:03 UTC, Dicebot wrote:
> I strictly believe any unittest enhancing library must be built on top of existing unittest blocks using __traits(getUnittest) and be 100% compatible with normal `-unittest` mode

I don't disagree. What exactly does that mean and what would it look like?

I'm not familiar with __traits(getUnittest). Is that something that could/should be used in what I'm doing?

What I'm missing, and apparently others in the original thread, is a way to run tests selectively. It is difficult to do with unittest because they are not named. If there were a way to annotate the test and pull them out that way it would be great. Can it be done?
October 25, 2013
On Friday, 25 October 2013 at 13:23:46 UTC, Daniel Davidson wrote:
> What I'm missing, and apparently others in the original thread, is a way to run tests selectively. It is difficult to do with unittest because they are not named. If there were a way to annotate the test and pull them out that way it would be great. Can it be done?

You can completely re-implement default test by using runtime hook http://wiki.dlang.org/Runtime_Hooks ("_d_unittest" should do AFAIK)

In that runner you can manually get all unittest blocks in the program as functions using __traits(getUnittest). One can make any custom decisions for running specific unittest blocks based on User-Defined Attributes attached to it.

Benefit of this approach is that the very same tests remain runnable in traditional out-of-the-box way if you don't use that library runner.

I remember Jacob Carlborg doing some experiments in that direction but did not track any further progress.
October 25, 2013
On Friday, 25 October 2013 at 13:30:54 UTC, Dicebot wrote:
> You can completely re-implement default test by using runtime hook http://wiki.dlang.org/Runtime_Hooks ("_d_unittest" should do AFAIK)

*default test runner
October 25, 2013
On Friday, 25 October 2013 at 13:30:54 UTC, Dicebot wrote:
> On Friday, 25 October 2013 at 13:23:46 UTC, Daniel Davidson wrote:
>> What I'm missing, and apparently others in the original thread, is a way to run tests selectively. It is difficult to do with unittest because they are not named. If there were a way to annotate the test and pull them out that way it would be great. Can it be done?
>
> You can completely re-implement default test by using runtime hook http://wiki.dlang.org/Runtime_Hooks ("_d_unittest" should do AFAIK)
>

Pretty sure this is what I'm doing. Only I did not know you could UDA a unittest.

> In that runner you can manually get all unittest blocks in the program as functions using __traits(getUnittest). One can make any custom decisions for running specific unittest blocks based on User-Defined Attributes attached to it.
>

Any samples of how to use __traits(getUnittest,...). I might be able to work as you suggest if I can get this to work.

> Benefit of this approach is that the very same tests remain runnable in traditional out-of-the-box way if you don't use that library runner.
>
> I remember Jacob Carlborg doing some experiments in that direction but did not track any further progress.

October 25, 2013
This will work starting with 2.064:

module a;

import std.stdio;

struct ID
{
    string data;
}

@ID("one")
unittest
{
    writeln("1");
}

@ID("two")
unittest
{
    writeln("2");
}

void main()
{
    import std.typetuple;
    alias tests = TypeTuple!( __traits(getUnitTests, a) );

    foreach (test; tests)
    {
        foreach (uda; __traits(getAttributes, test))
        {
            static if (is(typeof(uda) == ID))
            {
                if (uda == ID("two"))
                    test();
            }
        }
    }
}

It will print stuff twice though because I didn't suppress native unittest runner. Didn't actually dwell deep into runtime hooks so don't know what is best way to do it (maybe we need one more enhancement for it)
October 25, 2013
On Friday, 25 October 2013 at 14:14:39 UTC, Dicebot wrote:
> This will work starting with 2.064:
>
> module a;
>
> import std.stdio;
>
> struct ID
> {
>     string data;
> }
>
> @ID("one")
> unittest
> {
>     writeln("1");
> }
>
> @ID("two")
> unittest
> {
>     writeln("2");
> }
>
> void main()
> {
>     import std.typetuple;
>     alias tests = TypeTuple!( __traits(getUnitTests, a) );
>
>     foreach (test; tests)
>     {
>         foreach (uda; __traits(getAttributes, test))
>         {
>             static if (is(typeof(uda) == ID))
>             {
>                 if (uda == ID("two"))
>                     test();
>             }
>         }
>     }
> }
>
> It will print stuff twice though because I didn't suppress native unittest runner. Didn't actually dwell deep into runtime hooks so don't know what is best way to do it (maybe we need one more enhancement for it)

This is great. I love the unittest blocks and UDAs. This way I can still have very easy-entry (as in "just write unittest {}") unittests while gaining the power of unittest frameworks.

It's a hell of a lot better than having some class with attributes containing methods with attributes, containing parameters with attributes :) I'm developing RSI when writing tests in other languages. (In Java I develop RSI just declaring variables...)
October 25, 2013
On Friday, 25 October 2013 at 13:04:03 UTC, Dicebot wrote:
> I strictly believe any unittest enhancing library must be built on top of existing unittest blocks using __traits(getUnittest) and be 100% compatible with normal `-unittest` mode

I agree, this should be easy to implement. In my unit testing framework i could add support to run only unit tests of one particular module but in the future when the above is released it would be easy to add it on a per test basis.
October 25, 2013
For information how to implement your own unit test handler see the bottom of the report module here:

https://github.com/nomad-software/dunit

From there you can selectively run tests based on some outside criteria. I think the new trait will open up further possibilities too.
« First   ‹ Prev
1 2