Giter Site home page Giter Site logo

atilaneves / unit-threaded Goto Github PK

View Code? Open in Web Editor NEW
120.0 13.0 37.0 1.51 MB

Advanced unit test framework for D

License: BSD 3-Clause "New" or "Revised" License

D 97.25% Shell 1.01% Python 1.40% Batchfile 0.35%
testing unittest unit-testing property-based-testing property-testing mocking mock dlang dlanguage integration-testing

unit-threaded's Introduction

unit-threaded

Build Status Coverage

My DConf2016 Lightning talk demonstrating unit-threaded.

Multi-threaded advanced unit test framework for the D programming language.

Augments D's unittest blocks with:

  • Tests can be named and individually run
  • Custom assertions for better error reporting (e.g. 1.should == 2)
  • Runs in threads by default
  • UDAs for customisation of tests
  • Property based testing
  • Mocking

Quick start with dub

Note: while getting started this way is easy, it also increases build times and may run into edge cases. See below for how to do it manually.

dub runs tests with dub test. Unfortunately, due to the nature of D's compile-time reflection, to use this library a test runner file listing all modules to reflect on must exist. Since this is a tedious task and easily automated, unit-threaded has a dub configuration called gen_ut_main to do just that. To use unit-threaded with a dub project, you can use a unittest configuration as exemplified in this dub.json:

{
    "name": "myproject",
    "targetType": "executable",
    "targetPath": "bin",
    "configurations": [
        { "name": "executable" },
        {
            "name": "unittest",
            "targetType": "executable",
            "preBuildCommands": ["$DUB run --compiler=$$DC unit-threaded -c gen_ut_main -- -f bin/ut.d -d $DUB"],
            "mainSourceFile": "bin/ut.d",
            "excludedSourceFiles": ["src/main.d"],
            "dependencies": {
                "unit-threaded": "*"
            }
        }
    ]
}

With dub.sdl:

configuration "executable" {
}

configuration "unittest" {
    dependency "unit-threaded" version="*"
    mainSourceFile "bin/ut.d"
    excludedSourceFiles "src/main.d"
    targetType "executable"
    preBuildCommands "$DUB run --compiler=$$DC unit-threaded -c gen_ut_main -- -f bin/ut.d -d $DUB"
}

excludedSourceFiles is there to not compile the file containing the main function to avoid linker errors. As an alternative to using excludedSourceFiles, the "real" main can be versioned out:

version(unittest) {
    import unit_threaded;
    mixin runTestsMain!(
        "module1",
        "module2",
        // ...
    );
} else {
    void main() {
        //...
    }
}

Manually listing the D modules with tests

Alternatively to the above and the recommended way is to manually (unfortunately) list all the modules with tests in the unittest main function. There's a mixin for that:

import unit_threaded;
mixin runTestsMain!(
    "mypkg.mymod0",
    "mypkg.mymod1",
    // ...
);

Your unittest blocks will now be run in threads and can be run individually. To name each unittest, simply attach a string UDA to it:

@("Test that 2 + 3 is 5")
unittest {
    assert(2 + 3 == 5);
}

You can also have multiple configurations for running unit tests, e.g. one that uses the standard D runtime unittest runner and one that uses unit-threaded:

"configurations": [
    {"name": "ut_default"},
    {
      "name": "unittest",
      "preBuildCommands: ["$DUB run --compiler=$$DC unit-threaded -c gen_ut_main -- -f bin/ut.d -d $DUB"],
      "mainSourceFile": "bin/ut.d",
      ...
    }
]

In this example, dub test -c ut_default runs as usual if you don't use this library, and dub test runs with the unit-threaded test runner.

To use unit-threaded's assertions or UDA-based features, you must import the library:

// Don't use `version(unittest)` here - if anyone depends on your code and
// doesn't depend on unit-threaded they won't be able to test their own
// code!
version(TestingMyCode) { import unit_threaded; }
else                   { enum ShouldFail; }  // so production builds compile

int adder(int i, int j) { return i + j; }

@("Test adder") unittest {
    adder(2, 3).shouldEqual(5);
}

@("Test adder fails", ShouldFail) unittest {
    adder(2, 3).shouldEqual(7);
}

If using a custom dub configuration for unit-threaded as shown above, a version block can be used on Have_unit_threaded (this is added by dub to the build).

Custom Assertions

Code speaks louder than words:

    1.should == 1;
    1.should.not == 2;
    1.should in [1, 2, 3];
    4.should.not in [1, 2, 3];

    void funcThrows() { throw new Exception("oops"); }
    funcThrows.shouldThrow;

    // or with .be
    1.should.be == 1;
    1.should.not.be == 2;
    1.should.be in [1, 2, 3];
    4.should.not.be in [1, 2, 3];

    // I know this is operator overload abuse. I still like it.
    [1, 2, 3].should ~ [3, 2, 1];
    [1, 2, 3].should.not ~ [1, 2, 2];
    1.0.should ~ 1.0001;
    1.0.should.not ~ 2.0;

See more in the unit_threaded.should module.

Fast compilation mode

Fast compilation mode. Set the version to unitThreadedLight and it will compile much faster, but with no error reporting and certain features might not work. Experimental support.

Advanced Usage: Attributes

@ShouldFail is used to decorate a test that is expected to fail, and can be passed a string to explain why. @ShouldFail should be preferred to @HiddenTest. If the relevant bug is fixed or not-yet-implemented functionality is done, the test will then fail, which makes them harder to sweep under the carpet and forget about.

Since code under test might not be thread-safe, the @Serial attribute can be used on a test. This causes all tests in the same module that have this attribute to be executed sequentially so they don't interleave with one another.

Although not the best practice, it happens sometimes that a test is flaky. It is recommended to fix the test, but as a stopgap measure the @Flaky UDA can be used to rerun the test up to a default number of 10 times. This can be customized by passing it a number (e.g. @Flaky(12));

The @Name UDA can be used instead of a plain string in order to name a unittest block.

unit-threaded uses D's package and module system to make it possible to select a subset of tests to run. Sometimes however, tests in different modules address cross-cutting concerns and it may be desirable to indicate this grouping in order to select only those tests. The @Tags UDA can be used to do that. Any number of tags can be applied to a test:

@Tags("foo", "tagged")
unittest { ... }

The strings a test is tagged with can be used by the test runner binary to constrain which tests to run either by selecting tests with or without tags:

./ut @foo ~@bar

That will run all tests that have the "foo" tag that also don't have the "bar" tag.

The @Setup and @Shutdown UDAs can be attached to a free function in a module. If they are, they will be run before/after each unittest block in a composite (usually a module). This feature currently only works for unittest blocks, not free functions. Classes could override setup and shutdown already.

Property-based testing

There is preliminary support for property-based testing. To check a property use the check function from unit_threaded.property with a function returning bool:

check!((int a) => a % 2 == 0);

The above example will obviously fail. By default check runs the property function with 100 random values, pass it a different runtime parameter to change that:

check!((int a) => a % 2 == 0)(10_000); // will still fail

If using compile-time delegates as above, the types of the input parameters must be explicitly stated. Multiple parameters can be used as long as each one is of one of the currently supported types.

Mocking

Classes and interfaces can be mocked like so:

interface Foo { int foo(int, string); }
int fun(Foo f, int i, string s) { return f.foo(i * 2, s ~ "stuff"); }

auto m = mock!Foo;
m.expect!"foo";
fun(m, 3, "bar");
m.verify; // throws if not called

To check the values passed in, pass them to expect:

m.expect!"foo"(6, "barstuff");
fun(m , 3, "bar");
m.verify;

Either call expect then verify or call expectCalled at the end:

fun(m, 3, "bar");
m.expectCalled!"foo"(6, "barstuff");

The return value is T.init unless returnValue is called (it's variadic):

m.returnValue!"foo"(2, 3, 4);
assert(fun(m, 3, "bar") == 2);
assert(fun(m, 3, "bar") == 3);
assert(fun(m, 3, "bar") == 4);
assert(fun(m, 3, "bar") == 0);

Structs can also be mocked:

int fun(T)(T f, int i, string s) { return f.foo(i * 2, s ~ "stuff"); }
auto m = mockStruct(2, 3, 4); // the ints are return values (none need be passed)
assert(fun(m, 3, "bar") == 2);
m.expectCalled!"foo"(6, "barstuff");

If a struct is needed that returns different types for different functions:

    auto m = mockStruct!(ReturnValues!("length", 5, 3),
                         ReturnValues!("greet", "hello", "g'day"));
    m.length.shouldEqual(5);
    m.length.shouldEqual(3);
    m.greet.shouldEqual("hello");
    m.grett.shouldEqual("g'day");

Structs that always throw:

{
    auto m = throwStruct;
    m.foo.shouldThrow!UnitTestException;
}

{
    auto m = throwStruct!MyException;
    m.foo.shouldThrow!MyException;
}

Command-line Parameters

To run in single-threaded mode, use -s.

There is support for debug prints in the tests with the -d switch. TestCases and test functions can print debug output with the function writelnUt available here.

Tests can be run in random order instead of in threads. To do so, use the -r option. A seed will be printed so that the same run can be repeated by using the --seed option. This implies running in a single thread.

Integration tests and a sandbox environment

If you want to write tests that read from and write to the file system, you can use the Sandbox struct from unit_threaded.integration like so:

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 default the sandbox main path is tmp/unit-threaded but you can change that by calling Sandbox.setPath

Test Registration and Test Runner

There are two example programs in the example folder, one with passing unit tests and the other failing, to show what the output looks like in each case. Because of the way D packages work, they must be run from the top-level directory of the repository.

The built-in D unittest blocks are included automatically, as seen in the output of both example programs (example.tests.pass_tests.unittest and its homologue in example_fail). A name will be automatically generated for them. The user can specify a name by decorating them with a string UDA or the included @Name UDA.

The easiest way to run tests is by doing what the failing example code does: mixing in runTestsMain() in runner.d with the modules containing the tests as compile-time arguments (as strings).

There is no need to register tests. The registration is implicit and happens with:

  • D's `unittest`` blocks
  • Functions with a camelCase name beginning with test (e.g. testFoo())
  • Classes that derive from TestCase and override test()

The modules to be reflected on must be specified when calling runTests or runTestsMain, but that's usually done as shown in the dub configuration above. Private functions are skipped. TestCase also has support for setup() and shutdown(), child classes need only override the appropriate functions(s).

Tests can be hidden with the @HiddenTest attribute. This means that particular test doesn't get run by default but can still be run by passing its name as a command-line argument. HiddenTest takes a compile-time string to list the reason why the test is hidden. This would usually be a bug id but can be anything the user wants.

Since D packages are just directories and there the compiler can't read the filesystem at compile-time, there is no way to automatically add all tests in a package. To mitigate this and avoid having to manually write the name of all the modules containing tests, a dub configuration called gen_ut_main runs unit-threaded as a command-line utility to write the file for you.

Related Projects

  • dunit: xUnit Testing Framework for D
  • DMocks-revived: a mock-object framework that allows to mock interfaces or classes
  • deject: automatic dependency injection
  • specd: a unit testing framework inspired by specs2 and ScalaTest
  • DUnit: a toolkit of test assertions and a template mixin to enable mocking

unit-threaded's People

Contributors

abscissa avatar aliak00 avatar andrepuel avatar atilaneves avatar benjaminschaaf avatar burner avatar dhasenan avatar dkorpel avatar drug007 avatar feepingcreature avatar fr86 avatar geod24 avatar ghost91- avatar gizmomogwai avatar grogancolin avatar inkrementator avatar joakim-brannstrom avatar john-colvin avatar kinke avatar mrsmith33 avatar o3o avatar radcapricorn avatar rjframe avatar russel avatar serialvelocity avatar shishkander avatar singingbush avatar skoppe avatar veelo avatar wolframw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

unit-threaded's Issues

JUnit XML output

It would be very nice to have opportunity to use unit-threaded with Jenkins/Hudson.

'dirName' should be imported form 'std.path' instead of 'std.file'

'dirName' should be imported form 'std.path' instead of 'std.file in 'source/unit_threaded/runtime.d', of 'master'.

Compiled with DMD64 D Compiler v2.072.0-master-2777fda.

Now:

47> import std.file : exists, DirEntry, dirEntries, isDir, SpanMode, tempDir, getcwd, dirName, mkdirRecurse;
48> import std.path : buildNormalizedPath, buildPath, baseName, relativePath, dirSeparator;

Should be:

47> import std.file : exists, DirEntry, dirEntries, isDir, SpanMode, tempDir, getcwd, mkdirRecurse;
48> import std.path : dirName, buildNormalizedPath, buildPath, baseName, relativePath, dirSeparator;

Using the runTests template

The gen_ut_main script writes a ut_main.d which appears to assume:

a) Dub is being used.
b) The Dub documentation is wrong and "all at once" is the default not "file at a time" as the documentation appears to claim.
c) The ut_main.d file is created in the project directory.
d) The source is in a directory source.

I am trying to get unit-threaded working from SCons (and Meson but that will have to wait pending working out how to do all source at once compiling). For a project with everything at the top level I have everything working (but you need an extra directory (SConsDub) that I haven't made public as yet) see https://github.com/russel/Factorial/tree/master/D.

For a project with a source and test-source structure, it seems impossible to get ut_main.d to compile with the SCons way of building. The project is at https://github.com/russel/ApproxGC, also needs the as yet unpublished SConsDub. I have failed to get Dub to be able to build the integration tests (the application and unittest buildwork fine), which may indicate either a problem with my understanding of Dub, or of unit-threaded. Or both.

For the work Dub unitests the ut_main.d file is:

//main
//Automatically generated by unit_threaded.gen_ut_main, do not edit by hand.
import std.stdio;
import unit_threaded;

int main(string[] args)
{
    writeln("\nAutomatically generated file ut_main.d");
    writeln(`Running unit tests from dirs ["."]`);
    return runTests!(
                     "main"
                     )
                     (args);
}

which indicates the runTests template assumes all the files are in the source directory. Compare this though to the "no structure" project:

//factorial
//Automatically generated by unit_threaded.gen_ut_main, do not edit by hand.
import std.stdio;
import unit_threaded;

int main(string[] args)
{
    writeln("\nAutomatically generated file ut_main.d");
    writeln(`Running unit tests from dirs ["."]`);
    return runTests!(
                     "factorial"
                     )
                     (args);
}
`` the file is in . not source. So the `runTests` template must have a search path. Trying to build the ApproxGC integrationtests with Dub, I get:

|> dub test --config=integrationtest
Generating test runner configuration 'approx-gc-test-integrationtest' for 'integrationtest' (executable).
Excluding main source file ut_main.d from test.
Source file '/home/users/russel/Repositories/Git/Masters/ApproxGC_D/test-source/main.d' not found in any import path.

I guess I need to fix this Dub build before progressing the SCons work further.

Whole list of errors

I don't know if I'm doing some thing wrong, but I get all these errors:

C:\jpro\dpro2\Test\UnitThread>dub test
Running custom 'unittest' configuration.
Performing "unittest" build using dmd for x86.
unit-threaded 0.6.26: building configuration "library"...
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(103,17): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(110,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(113,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(118,23): Error: none of the overloads of 'ctor' are callable using argument types (string[], string, ulong), candidates are:
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\should.d(23,5): unit_threaded.should.UnitTestException.this(const(string) msg, string file = __FILE
, uint line = cast(uint)LINE, Throwable next = null)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\should.d(29,5): unit_threaded.should.UnitTestException.this(const(string[]) msgLines, string file = FILE, uint line = cast(uint)LINE, Throwable next = null)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(167,14): Error: template instance unit_threaded.mock.mock!(Foo) error instantiating
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(103,17): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(110,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(113,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(118,23): Error: none of the overloads of 'ctor' are callable using argument types (string[], string, ulong), candidates are:
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\should.d(23,5): unit_threaded.should.UnitTestException.this(const(string) msg, string file = __FILE
, uint line = cast(uint)LINE, Throwable next = null)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\should.d(29,5): unit_threaded.should.UnitTestException.this(const(string[]) msgLines, string file = FILE, uint line = cast(uint)LINE, Throwable next = null)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(186,18): Error: template instance unit_threaded.mock.mock!(Foo) error instantiating
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(103,17): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(110,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(113,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(118,23): Error: none of the overloads of 'ctor' are callable using argument types (string[], string, ulong), candidates are:
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\should.d(23,5): unit_threaded.should.UnitTestException.this(const(string) msg, string file = __FILE
, uint line = cast(uint)LINE, Throwable next = null)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\should.d(29,5): unit_threaded.should.UnitTestException.this(const(string[]) msgLines, string file = FILE, uint line = cast(uint)LINE, Throwable next = null)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(217,14): Error: template instance unit_threaded.mock.mock!(Foo) error instantiating
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(103,17): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(110,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
........\Users\Joel\AppData\Roaming\dub\packages\unit-threaded-0.6.26\source\unit_threaded\mock.d(113,21): Error: function unit_threaded.should.fail (const(string) output, const(string) file, const(uint) line) is not callable using argument types (string, string, ulong)
dmd failed with exit code 1.

Emit Failures as one-liners with file and line numbers.

Current output (single threaded mode):
basic_tests.Failure Test:
source\basic_tests.d:12 - unittest failure
basic_tests.Failure Test Dos:
source\basic_tests.d:18 - unittest failure
basic_tests.Sum Test:
Test "basic_tests.Failure Test" failed.
Test "basic_tests.Failure Test Dos" failed.

Request Output:
Test "basic_tests.Sum Test" succeeded;
Test "basic_tests.Failure Test" failed; source\basic_tests.d:12 - unittest failure
Test "basic_tests.Failure Test Dos" failed; source\basic_tests.d:18 - unittest failure

Rationale:

  • Multi-threaded unit tests can interleave the test names and exception printouts. This makes it difficult to tie failure reason/file/line ("source\basic_tests.d:18 - unittest failure") to the name of the test it failed on. Forced to use single-threaded mode to guarantee that information is on the following line.
  • The test printout at the end does not specify the reason the test failed.

By having the results on one-line, at the end, with file and line number, it avoids interleaving the printout and simplifies writing regular expressions to detect these failures in the output.

Wrong symbol resolution

foo.d:

module foo;

struct foo
{
}

test.d:

import foo;
import unit_threaded.runner;

int main(string[] args)
{
return args.runTests!(foo);
}

building fails because foo.foo is got as package.module instead of module.structure. I make bindings to GSL and there is a file gsl_rng that has struct gsl_rng and that prevents tests from building.

public AliasSeq breaks test function discovering

Every member of a module will be checked with isSomeFunction. isSomeFunction expects exactly one argument, but having a public AliasSeq will pass in multiple arguments.

Pull request on the way.

A few extra should...

Hey,

Would it be possible to add:
shouldNotBeEmpty, shouldBeEmpty, shouldHaveSize, shouldBeBiggerThan, shouldBeSmallerThan for arrays and associative arrays?

Thanks,
Nebster

setup/shutdown for multiple tests

As far as I can see, setup/shutdown only works for TestCase, which only supports a single test. Is that something that could be improved, either to allow setup/shutdown for global functions/unittests or allow multiple tests in a single TestCase? Ideally both 😃.

Integrating randomized benchmark and unittest into unit-threaded

so before spending to much time of coding lets think a little. I know crazy.

unit-threaded has the nice feature of also testing function with prefix "test"

my quick(fix->check) benchmarking clone works with functions like

void theFunctionToTest(Gen!(int, 1, 5) a, Gen!(float, 0.0, 10.0) b)   {
        // This will always be true
        assert(a >= 1 && a <= 5);
        assert(a >= 0.0 && a <= 10.0);

        // super expensive operation
        auto rslt = (a + b);
        doNotOptimizeAway(rslt);

        debug
        {
            assert(rslt > 1.0);
        }
    }

Replace theFunctionToTest with testFunctionToTest and we are in business.
Gen!T are structs that have an alias this to T the second and third parameter allow to specify a range.
Maybe some UDAs would be good to specify how often the function should be tested with random values in the given ranges, but that shouldn't be to hard.
When these functions are used for benchmarking it is necessary that they run singled threaded. The resulting is done in a csv file. I wrote a very small tool that then takes the csv and gnuplot to plot the results.

@atilaneves what do you think?

Readme.md sample configuration missing targetType for dub

Going to give unit-threaded a try (looks awesome by the way, great job on it and thanks a lot beforehand). Unfortunately, as stupid as it might seem, I spent well over 10 minutes trying to understand why I was getting this error:

Source file '<projectDir>/bin/ut.d' not found in any import path.

Thing is, I basically copy-pasted the README.md's dub sample configuration. It doesn't produce any errors, but neither does it seem to generate "bin/ut.d". The source of the problem is the lack of the "targetType" option for the "unittest" configuration.

Fastest fix ever, I guess. Just adding one line. Or maybe I missed on something, did I?

"targetType" : "executable" does the trick, of course.

Something weird is going wrong on travis.

Travis builds are failing, but it started with my earlier pull, #41, which changed nothing but the inside of a comment (which obviously couldn't have been the cause of these build failures). No idea what's actually going wrong.

Fixture isn't smooth enough?

It's may be my misunderstanding, but I can manage to use fixture the following way:

module mytest;
import unit_threaded;
import unit_threaded.runner;

class Fixture: TestCase
{
    override void setup()
    {
        // do initialization common for test1 and test2
    }

    // if uncomment this it works else runtime error
    //override void test()
    //{
    //}
}

class Test1: Fixture
{
    override void test()
    {
        // testing feature #1
    }
}

class Test2: Fixture
{
    override void test()
    {
        // testing feature #2
    }
}

int main(string[] args)
{
    return args.runTests!(
        "mytest",
    ); 
}

this code fails in runtime with:

(gdb) r
Starting program: /home/drug/workspace/rdpl-test/rdpl-test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff626b700 (LWP 15979)]

Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) bt
#0  0x0000000000000000 in ?? ()
#1  0x00000000008486a3 in object.TypeInfo_Class.getHash() ()
#2  0x000000000084d9c3 in _aaGetImpl ()
#3  0x000000000084d903 in _aaGetY ()
#4  0x000000000082be5a in unit_threaded.factory.createTestCases() (testsToRun=..., testData=...)
    at ../../.dub/packages/unit-threaded-0.5.2/source/unit_threaded/factory.d:46
#5  0x0000000000828a51 in unit_threaded.runner.runTests() (testData=..., options=...)
    at ../../.dub/packages/unit-threaded-0.5.2/source/unit_threaded/runner.d:57
#6  0x00000000008289da in unit_threaded.runner.runTests() (testData=..., args=...)
    at ../../.dub/packages/unit-threaded-0.5.2/source/unit_threaded/runner.d:44
#7  0x000000000070c223 in unit_threaded.runner.__T8runTestsVAyaa6_6d7974657374Z.runTests() (args=...)
    at ../../.dub/packages/unit-threaded-0.5.2/source/unit_threaded/runner.d:27
#8  0x00000000006ecd08 in D main (args=...) at source/app.d:127
#9  0x000000000084f3ef in rt.dmain2._d_run_main() ()
#10 0x000000000084f342 in rt.dmain2._d_run_main() ()
#11 0x000000000084f3a8 in rt.dmain2._d_run_main() ()
#12 0x000000000084f342 in rt.dmain2._d_run_main() ()
#13 0x000000000084f2bc in _d_run_main ()
#14 0x000000000077e43d in main ()
(gdb)

I guess it don't find test1 and test2 and so fails trying run empty set of tests. Workaround (adding empty test() in the fixture as in commented code above) works but adds extra useless test.

Mocking a class - returnValue!("func")

When mocking a classes return value, mock!"" fails with something like the following:

../../.dub/packages/unit-threaded-0.7.22/unit-threaded/source/unit_threaded/mock.d-mixin-199(199,1): Error: undefined identifier 'vmnames_0_returnValues'
../../.dub/packages/unit-threaded-0.7.22/unit-threaded/source/unit_threaded/mock.d(182,41): Error: template instance unit_threaded.mock.Mock!(Hyp).Mock.returnValue!(0, "vmnames", string[]) error instantiating
source/model.d(348,32):        instantiated from here: returnValue!("vmnames", string[])

The class looks something like:

class Hyp{
    this(){} // this is also required for mocking a class
    string[] vmnames(){
        // return array of vmnames
         .....
    }
}

If I create an interface to model the Hyp object, and mock using that, it all works swimmingly.

@ShouldFail tests are treated exactly the same as regular tests

When writing something new (especially when using TTD) often its the case that
you have one or more tests which have to pass at some point in the future. Maybe
they are for a separate component, maybe you have multiple tests that rely on
each other and you're working on getting one to pass at a time.

As is the case in unit-threaded one would normally mark these tests as
"expected to fail" or "should fail". What I would then expect to happen is that
these tests would run, but would only be reported if the unexpected happened,
ie. they succeeded. Instead they seem to get reported whether they fail or not,
in the same way other tests get reported.

Tests that fail

@ShouldFail
void testShouldFail() {
    assert(false);
}

Report:

Test testShouldFail failed.


Time taken: 4 ms, 690 μs, and 6 hnsecs
67 test(s) run, 1 failed, 1 failing as expected.

Unit tests failed!

Error executing command test:
Program exited with code 1

Tests that succeed

Code:

@ShouldFail
void testShouldFail() {
    assert(true);
}

Report:

Test testShouldFail failed.


Time taken: 4 ms, 356 μs, and 8 hnsecs
67 test(s) run, 1 failed, 1 failing as expected.

Unit tests failed!

Error executing command test:
Program exited with code 1

From the documentation in the README this doesn't seem like intended
behaviour, but I may be wrong on that front.

Function overloading issue

I have:

interface IChannel {
   ubyte[] send(const(ubyte[]) msg);
   string send(string msg);
}
class Channel: IChannel {
   ubyte[] send(const(ubyte[]) msg) {
      return [0];
   }
   string send(string msg) {
      return "foo";
   }
}
class Client {
   private IChannel chan;
   this(IChannel chan) {
      assert(chan !is null);
      this.chan = chan;
   }
   void use() {
      const(ubyte[]) buf = [0, 1, 2];
      chan.send(buf);
   }
}
unittest {
   auto chan = mock!IChannel;
   const(ubyte[]) buf = [0, 1, 2];
   chan.expect!"send"(buf);

   auto c = new Client(chan);
   c.use();
   chan.verify();
}
$ dub test 
./../../.dub/packages/unit-threaded-0.7.13/unit-threaded/source/unit_threaded/mock.d(158,5): Error: class unit_threaded.mock.Mock!(IChannel).Mock.MockAbstract interface function 'string send(string msg)' is not implemented

If I change

string send(string msg) {

to

string sendMsg(string msg) {

it works.

Thank you

How to use unit-threaded from SCons or Meson?

Currently instructions say how to use unit-threaded with Dub – using JSON syntax, should add examples with SDLang suntax as well. It should be possible to use unit-threaded in SCons and Meson builds. In the short term this would be how to use Dub to get the package and run things explicitly from the command line. This can then be transformed into "plugins" to SCons and Meson to get dependencies from the Dub repository using the API. I guess CMake should be added to the mix as well.

I am happy to do the SCons version of this first as a trial to then see how to do it is Meson and possibly CMake.

cast problem in safe code

When I compile:

module tests.array;

import unit_threaded;

interface IService { }
class Service: IService { }

@UnitTest
void cast_not_allowed() {
   IService x = new Service();
   IService y = new Service();
   checkEqual(x, y);
}

the compiler complains:

unit-threaded/source/unit_threaded/check.d(36): Error: cast from const(IService) to const(Object) not allowed in safe code
unit-threaded/source/unit_threaded/check.d(36): Error: cast from const(IService) to const(Object) not allowed in safe code
array.d(13): Error: template instance unit_threaded.check.checkEqual!(IService, IService) error instantiating

My compiler:

$ dmd --version

DMD64 D Compiler v2.067

Thank you

@Values("string") / getValue!(string) not returning correct value

    @("Test_parse_hostgroup")
    @Values("abc", "abc1", "abc.xyz", "abc1.xyz", "abc12345.xyz.asd")
    unittest{
        string val = getValue!(string);
        writeln("Value: ", val);
        val.hostgroup.shouldEqual("abc");
    }

That prints:

unit_threaded.should.UnitTestException@source/model.d(729): Expected: "abc"
     Got: ""

I've checked and double checked, don't think I'm doing anything too strange here.
Any ideas?

Mock fails if the mocked object imports something

I have a problem if the mocked function's parameters type or return type is imported from a different module.

Here is a short example:

example/example_pass.d:

import unit_threaded.runner;

import tests.pass.mock;

int main(string[] args) {
    return args.runTests!(
        tests.pass.mock,
    );
}

tests/pass/types.d:

module tests.pass.types;

struct A
{
}

tests/pass/mock.d:

module tests.pass.mock;

import tests.pass.types;
import unit_threaded;

@safe pure unittest {
    interface Foo {
        A foo() @safe pure;
    }

    A fun(Foo f) {
        return f.foo();
    }

    auto m = mock!Foo;
    m.expect!"foo";
    fun(m);
}

I'm getting the following output:

Running custom 'unittest' configuration.
Performing "unittest" build using dmd for x86_64.
unit-threaded 0.7.2+commit.30.g0b01cd2: building configuration "unittest"...
Warning: testIssue31 passes the criteria for a value-parameterized test function but doesn't have the appropriate value UDAs.
Consider changing its name or annotating it with @DontTest
source/unit_threaded/mock.d-mixin-156(156,5): Error: undefined identifier 'A'
source/unit_threaded/mock.d-mixin-156(158,12): Error: undefined identifier 'A'
source/unit_threaded/mock.d(173,14): Error: template instance unit_threaded.mock.Mock!(Foo, "tests.pass.mock") error instantiating
tests/pass/mock.d(15,14): instantiated from here: mock!(Foo, "tests.pass.mock")
dmd failed with exit code 1.

I've found a workaround. If I make "tests.pass.types" to a public import, then it compiles, but it doesn't seem to be supposed to work this way.

Windows: Symbol Undefined _mkdtemp

Building on windows gave me Symbol Undefined _mkdtemp.
I worked around this by replacing

extern(C) char* mkdtemp(char*);

with

version(Windows) {
    extern(C) int mkdir(char*);
    extern(C) char* mktemp(char*);
    char* mkdtemp(char* t) {
        char* result = mktemp(t);
        if (result is null) return null;
        if (mkdir(result)) return null;
        return result;
    }
} else {
    extern(C) char* mkdtemp(char*);
}

Then I was presented with

unit_threaded.should.UnitTestException@source\unit_threaded\integration.d(173): Expected: ["foo", "toto"]
     Got: ["foo\r", "toto"]

After much digging I found out that the test file is being created with File.writeln which uses LockingTextWriter which uses fputc which on windows changes \n to \r\n.

I can think of 2 solutions to this

  1. change shouldEqualLines to strip \r
  2. change how the test file is being created.

I think option 1 would be the better solution.

cartesianProduct involving finite ranges...

I am trying to move from another unit-testing lib to yours, but am getting this problem.

(also had a problem with a module that was called config, classing with std.getopt.config, but that was solved by renaming my module)

Can you help me explain what is going on here, and how to work around?

/usr/include/dmd/phobos/std/algorithm/setops.d(119,10): Error: static assert "cartesianProduct involving finite ranges must have at least one finite forward range"
../../.dub/packages/unit-threaded-0.6.22/unit-threaded/source/unit_threaded/reflection.d-mixin-381(381,29): instantiated from here: cartesianProduct!(void[], void[])
../../.dub/packages/unit-threaded-0.6.22/unit-threaded/source/unit_threaded/reflection.d(445,25): instantiated from here: createTestData!(test, "testHeader")
../../.dub/packages/unit-threaded-0.6.22/unit-threaded/source/unit_threaded/reflection.d(341,12): instantiated from here: moduleTestData!(test, isTestFunction, createFuncTestData)

Are release and unittests builds different?

When using Dub, there is a build of unit-threaded for each build type, which is not unreasonable per se. But is there a difference between the release and unittest build of unit-threaded for a given build? Is there a reason not to use a release build of unit-threaded for running tests?

Mock error: '_impl is not accessible'

I've this code

// tests/foo.d
//--------------
module tests.foo;
import unit_threaded;
interface Foo {
   int foo(int, string) @safe pure;
   void bar() @safe pure;
}

void testFoo() {
   auto m = mock!Foo;
   m.expect!"foo";
}
$ dub test

tests/foo.d(12,4): Deprecation: unit_threaded.mock.Mock!(Foo).Mock._impl is not visible from module tests.foo
tests/foo.d(12,4): Error: struct unit_threaded.mock.Mock!(Foo).Mock member _impl is not accessible

My environment

$ dmd --version
DMD64 D Compiler v2.071.1

$ dub --version
DUB version 1.0.0, built on Jun 21 2016

$ uname --all
Linux snowball 4.6.4-1-ARCH #1 SMP PREEMPT Mon Jul 11 19:12:32 CEST 2016 x86_64 GNU/Linux

Here you can find the complete project

Thanks

Compiling error

$ dub build

Running dmd...
unit_threaded/io.d(59): Error: pure function 'unit_threaded.io.green' cannot access mutable static data '_escCodes'
unit_threaded/io.d(59): Error: pure function 'unit_threaded.io.green' cannot access mutable static data '_escCodes'
unit_threaded/io.d(63): Error: pure function 'unit_threaded.io.red' cannot access mutable static data '_escCodes'
unit_threaded/io.d(63): Error: pure function 'unit_threaded.io.red' cannot access mutable static data '_escCodes'
Error: DMD compile run failed with exit code 1

$dmd --help

DMD64 D Compiler v2.063.2
Copyright (c) 1999-2013 by Digital Mars written by Walter Bright
...

Can't run tests

Hi,

I'm trying to setup your library in my project, but it seams that it does not work...

here is my config:

    "configurations": [
        { "name": "executable" },
        {
            "name": "unittest",
            "_preBuildCommands": ["dub run unit-threaded -c gen_ut_main -- -f bin/ut.d"],
            "mainSourceFile": "bin/ut.d",
            "excludedSourceFiles": ["src/app.d"],
            "dependencies": {
                "unit-threaded": "~>0.6.0"
            }
        }
    ]

and the output:

➜  altap git:(motor-updates) ✗ dub test
Running custom 'unittest' configuration.
Performing "unittest" build using dmd for x86_64.
tinyendian 0.1.2: target for configuration "library" is up to date.
dyaml 0.5.3: target for configuration "library" is up to date.
vibe-d:utils 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:data 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:core 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "libevent" is up to date.
vibe-d:http 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:diet 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:mail 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:mongodb 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:redis 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d:web 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "library" is up to date.
vibe-d 0.7.29-beta.1+commit.14.gbdf8b14: target for configuration "libevent" is up to date.
swaggerize 0.1.4: target for configuration "library" is up to date.
crate ~master: target for configuration "library" is up to date.
unit-threaded 0.6.17: target for configuration "library" is up to date.
alttap-webapi ~motor-updates: building configuration "unittest"...
../../.dub/packages/unit-threaded-0.6.17/unit-threaded/source/unit_threaded/reflection.d-mixin-50(50,8): Error: module alttapMotors is in file 'altap/hardware/alttapMotors.d' which cannot be read
import path[0] = source/
import path[1] = crate/source/
import path[2] = ../../.dub/packages/swaggerize-0.1.4/swaggerize/source/
import path[3] = ../../.dub/packages/dyaml-0.5.3/dyaml/source
import path[4] = ../../.dub/packages/tinyendian-0.1.2/tinyendian/source
import path[5] = ../vibe.d/source/
import path[6] = ../../.dub/packages/libevent-2.0.1_2.0.16/libevent
import path[7] = ../../.dub/packages/openssl-1.1.4_1.0.1g/openssl
import path[8] = ../../.dub/packages/unit-threaded-0.6.17/unit-threaded/source/
import path[9] = /Library/D/dmd/src/phobos
import path[10] = /Library/D/dmd/src/druntime/import
dmd failed with exit code 1.

Warning and error with dmd 2.067

$ dub build --compiler=dmd
Building unit-threaded 0.4.6+commit.14.gd5f4f46 configuration "library", build type debug.
Running dmd...
source/unit_threaded/check.d(12): Warning: instead of C-style syntax, use D-style syntax 'string[] msgLines'
FAIL .dub/build/library-debug-linux.posix-x86_64-dmd_2067-E01F1700C0BD032EA95AD49F17AEDCD5/ unit-threaded staticLibrary
Error executing command build:
dmd failed with exit code 1.

Dmd version:

dmd --version
DMD64 D Compiler v2.067

template instance GetTypes!uint does not match template declaration GetTypes(alias T)

Hello,

I have a file mymed/color.d:

module mymed.color;
alias RGB = uint;

When I run dub test, it outputs following errors:

Running ../../../../home/nmtigor/.dub/packages/unit-threaded-0.6.16/unit-threaded/unit-threaded -f bin/ut.d
../../../../home/nmtigor/.dub/packages/unit-threaded-0.6.16/unit-threaded/source/unit_threaded/reflection.d(316,27): Error: template instance GetTypes!uint does not match template declaration GetTypes(alias T)
../../../../home/nmtigor/.dub/packages/unit-threaded-0.6.16/unit-threaded/source/unit_threaded/reflection.d(260,45): Error: template instance unit_threaded.reflection.moduleTestFunctions!(color).moduleTestFunctions.pred!(color, "RGB") error instantiating

Is it a bug? When I set version to "==0.6.4", it works fine.

Reflection error when module is named "test.XXX"

Code that exhibit the error:

/+ dub.sdl:
   name "example"
   dependency "unit-threaded" version="~>0.6.24"
+/
module test.fun;
import unit_threaded;

unittest {
    assert(true);
}

int main(string[] args) {
    return args.runTests!("test.fun");
}

Running:

bash$ dub test --single example.d
Package example (configuration "application") defines no import paths, use {"importPaths": [...]} or the default package directory structure to fix this.
Configuration 'application' does not output a library. Falling back to "dub -b unittest -c application".
Performing "unittest" build using dmd for x86_64.
unit-threaded 0.6.25: building configuration "library"...
example ~master: building configuration "application"...
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/reflection.d(94,43): Error: argument test has no parent
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/reflection.d(116,25): Error: template instance unit_threaded.reflection.moduleUnitTests!(fun).moduleUnitTests.unittestName!(__unittestL9_1, 0) error instantiating
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/reflection.d(176,9):        instantiated from here: addMemberUnittests!(fun)
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/reflection.d(200,5):        instantiated from here: addUnitTestsRecursively!(fun)
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/reflection.d-mixin-62(62,1):        instantiated from here: moduleUnitTests!(fun)
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/reflection.d(71,12):        ... (2 instantiations, -v to show) ...
../../.dub/packages/unit-threaded-0.6.25/unit-threaded/source/unit_threaded/runner.d(46,27):        instantiated from here: allTestData!"test.fun"
example.d(14,16):        instantiated from here: runTests!"test.fun"
dmd failed with exit code 1.

Changing the module name to, for example, "gun.fun" makes the error go away.

ps. Thank you for a superb framework. I really like it.
The most significant improvements over the standard runner has for me been:

  • Shorter runtime when the tests are running in parallel.
  • Better reporting of failed tests. Both being able to add descriptions to how the tests are presented. This includes how the shouldXXX-functions work.

Yes, the other features are really nice too. They improve the quality of the tests.

Strange output behavior

Hi ...

I am developing a small library (read only git access) that behaves strange when running its unit-tests.
Most of the time, I do not get output, but sometimes, my debug output appears. I always run the tests with the same random seed (please see snippet ...).
Could it be me, that is somehow corrupting the state of the unit-test flags?

~/D/D///g/dgit on(master) is(dirty) ➜ dub test -- --seed 0 538ms
Running custom 'unittest' configuration.
Performing "unittest" build using dmd for x86_64.
unit-threaded 0.7.4: target for configuration "library" is up to date.
dgit 1.0.0: target for configuration "unittest" is up to date.
To force a rebuild of up-to-date targets, run again with --force.
Running ./dgit --seed 0

Automatically generated file gen/ut.d
Running unit tests from dirs ["."]
dgit.consumeSourceLength:
dgit.consumeSourceOffset:
dgit.consumeTypeAndSizeHeader:
dgit.decodeDeltaEncoding:
dgit.deltaDecodingOfPack:
dgit.offsetVarint:
dgit.varint:
dgit.visitors.FileVisitor:
dgit.visitors.FileVisitor.files:
asciitable.unittest0:
dgit.binarysearch indexOf:
dgit.visitors.StatusVisitor:
dgit.visitors.ShowVisitor:

Time taken: 58 ms, 926 μs, and 4 hnsecs
13 test(s) run, 0 failed.

OK!

~/D/D///g/dgit on(master) is(dirty) ➜ dub test -- --seed 0 428ms
Running custom 'unittest' configuration.
Performing "unittest" build using dmd for x86_64.
unit-threaded 0.7.4: target for configuration "library" is up to date.
dgit 1.0.0: target for configuration "unittest" is up to date.
To force a rebuild of up-to-date targets, run again with --force.
Running ./dgit --seed 0

Automatically generated file gen/ut.d
Running unit tests from dirs ["."]
.git/objects/pack/pack-634357003a90cc0709ec11c5ec4cdc2e148969bb.idx mmap first bytes: [255, 116, 79, 99, 0, 0, 0, 2, 0, 0]
objectNames: ["00b6ad768cfc3a30a9c557ca26860dd0a088ea41", "05c1fa5802071e0b24201ea42a9c7e9fff85f196", "0b896c9ed2455599fd6af093d87bae3156ec6b0a", "1364647013992cc48477a9ca9065986e51807cab", "164f484cf0c8ed53293c3536ab4707634218accb", "246d0192bb436de9083c2337b33675f37a5d76c5", "29a6887eb108d2010bd9ffb8c87dba99f2c60295", "2a9d81d80b3c39f4f06e1cfdc172e2b0451210a8", "2d3dcc530037db93799a30efa60fc89214adbd1a", "39cdcd4822c7250fb5f1b39828e24fb62695d2ea", "3d34e56be5cf5e673c915751215839467ccbd2f5", "406afcad7a542845477d538fd68ea2a9aeb24ba0", "40e01c1ca691ea7920b07a6ab3aabeb701a65984", "49664b855e876af6a482d704867cd1240ab05b5b", "4a484b5fd9ddfeefac0f87077ec1300ae42221c6", "4ead87a7b634a19acbaa4f05ade917a2e8f7eba1", "554dc72fca945090a05e683279b6cb929819b7b7", "55f2dc979a49e58eb1c55e199dcb1b2e1365d5fc", "5bf7deff7399a4e6157c059cdf044adf155b7817", "61671a996989bbbddf6379175a1a3e502badcaf0", "704dae6df39317abb7408621caf837b639b943a5", "741c34f28661dd004cb132731ceef42ae9ae766d", "8d53596808f83aea639a89f40ffb97232a334fcb", "8e65723f4a475773a1010c7ac332f0a66a5340d1", "92efd5f67dcd642ccce8259fc9d38b84f64419d1", "9332dcfdaf2d2f5ed947e7e5599a111c91ec2f51", "9b5a37e48e57f64d85485211e7f096a1ee399539", "9b804e2b947a95d368ad3a5bac1012a39fe571e0", "9c19fd02e8f4191ef8be2b89f0af3474cad26dce", "a151256d55cb393acb8343cf91f235129ed5a56a", "a2559ff27f8c85334ef0dbe55b5a49630dd0d485", "a715a4b6cee5316fdc67019ca6f23452b24c9d4d", "ab0ab0893920c8afd8b12bcc802ac1f342126b89", "af661f0382f28fb2762b317b87ed2e204321a9e9", "ba22483dbf2d18edf7518f04faf2ff5bfe5c19fc", "ce39a9ebbdac39ac513b9f6bbd0bdcf3eedfee66", "ce80dba8059ecb0c813de537ddda36922c51a6fe", "d392c64bb6201d5146a19522d6fc9b812ec839a9", "d7193e77aed2f36610e2f9c9eeeb002da65e827a", "dad64bbf4045d87285850105683324d774040ed2", "dbc0eaf384fd24bb0bd4a2c41229e49069158bc0", "df69fc33409c177a86f891a83829d5fd932f8626", "ec624fe85a0a4113f01f6cb69356092b19591387", "eec6d03821141160d0439c896de1e431c192718e", "f58f05ab34bf945d658647b288839ed352a71db6", "f7322f49878e1b67908a4533f618a850d5e9c8ce", "f91c825a5dec0161042b02e53bed5c2b0f10815c"]47
asciitable.unittest0:
dgit.binarysearch indexOf:
dgit.consumeSourceLength:
dgit.consumeSourceOffset:
dgit.consumeTypeAndSizeHeader:
dgit.decodeDeltaEncoding:
dgit.deltaDecodingOfPack:
dgit.varint:
dgit.visitors.FileVisitor:
dgit.offsetVarint:
dgit.visitors.FileVisitor.files:
dgit.visitors.ShowVisitor:
dgit.visitors.StatusVisitor:

Time taken: 60 ms, 256 μs, and 1 hnsec
13 test(s) run, 0 failed.

OK!

~/D/D///g/dgit on(master) is(dirty) ➜ dub test -- --seed 0 342ms
Running custom 'unittest' configuration.
Performing "unittest" build using dmd for x86_64.
unit-threaded 0.7.4: target for configuration "library" is up to date.
dgit 1.0.0: target for configuration "unittest" is up to date.
To force a rebuild of up-to-date targets, run again with --force.
Running ./dgit --seed 0

Automatically generated file gen/ut.d
Running unit tests from dirs ["."]
.git/objects/pack/pack-634357003a90cc0709ec11c5ec4cdc2e148969bb.idx mmap first bytes: [255, 116, 79, 99, 0, 0, 0, 2, 0, 0]
objectNames: ["00b6ad768cfc3a30a9c557ca26860dd0a088ea41", "05c1fa5802071e0b24201ea42a9c7e9fff85f196", "0b896c9ed2455599fd6af093d87bae3156ec6b0a", "1364647013992cc48477a9ca9065986e51807cab", "164f484cf0c8ed53293c3536ab4707634218accb", "246d0192bb436de9083c2337b33675f37a5d76c5", "29a6887eb108d2010bd9ffb8c87dba99f2c60295", "2a9d81d80b3c39f4f06e1cfdc172e2b0451210a8", "2d3dcc530037db93799a30efa60fc89214adbd1a", "39cdcd4822c7250fb5f1b39828e24fb62695d2ea", "3d34e56be5cf5e673c915751215839467ccbd2f5", "406afcad7a542845477d538fd68ea2a9aeb24ba0", "40e01c1ca691ea7920b07a6ab3aabeb701a65984", "49664b855e876af6a482d704867cd1240ab05b5b", "4a484b5fd9ddfeefac0f87077ec1300ae42221c6", "4ead87a7b634a19acbaa4f05ade917a2e8f7eba1", "554dc72fca945090a05e683279b6cb929819b7b7", "55f2dc979a49e58eb1c55e199dcb1b2e1365d5fc", "5bf7deff7399a4e6157c059cdf044adf155b7817", "61671a996989bbbddf6379175a1a3e502badcaf0", "704dae6df39317abb7408621caf837b639b943a5", "741c34f28661dd004cb132731ceef42ae9ae766d", "8d53596808f83aea639a89f40ffb97232a334fcb", "8e65723f4a475773a1010c7ac332f0a66a5340d1", "92efd5f67dcd642ccce8259fc9d38b84f64419d1", "9332dcfdaf2d2f5ed947e7e5599a111c91ec2f51", "9b5a37e48e57f64d85485211e7f096a1ee399539", "9b804e2b947a95d368ad3a5bac1012a39fe571e0", "9c19fd02e8f4191ef8be2b89f0af3474cad26dce", "a151256d55cb393acb8343cf91f235129ed5a56a", "a2559ff27f8c85334ef0dbe55b5a49630dd0d485", "a715a4b6cee5316fdc67019ca6f23452b24c9d4d", "ab0ab0893920c8afd8b12bcc802ac1f342126b89", "af661f0382f28fb2762b317b87ed2e204321a9e9", "ba22483dbf2d18edf7518f04faf2ff5bfe5c19fc", "ce39a9ebbdac39ac513b9f6bbd0bdcf3eedfee66", "ce80dba8059ecb0c813de537ddda36922c51a6fe", "d392c64bb6201d5146a19522d6fc9b812ec839a9", "d7193e77aed2f36610e2f9c9eeeb002da65e827a", "dad64bbf4045d87285850105683324d774040ed2", "dbc0eaf384fd24bb0bd4a2c41229e49069158bc0", "df69fc33409c177a86f891a83829d5fd932f8626", "ec624fe85a0a4113f01f6cb69356092b19591387", "eec6d03821141160d0439c896de1e431c192718e", "f58f05ab34bf945d658647b288839ed352a71db6", "f7322f49878e1b67908a4533f618a850d5e9c8ce", "f91c825a5dec0161042b02e53bed5c2b0f10815c"]47

Missing import path

I tried setting up a minimal project as in the example, but get the following error

$ dub test
Generating test runner configuration '__test__unittest__' for 'unittest' (library).
Source file '/home/edwin/Documents/code/delaunay/bin/ut.d' not found in any import path.

My dub.json is:

{
    "name": "delaunay",
    "authors": [
        "Edwin van Leeuwen"
    ],
    "description": "Delaunay triangulation algorithm written in D.",
    "copyright": "Copyright © 2016, Edwin van Leeuwen",
    "license": "BSL-1.0",
    "configurations": [
        { "name": "delaunay" },
        {
            "name": "unittest",
            "preBuildCommands": ["dub run unit-threaded -c gen_ut_main -- -f bin/ut.d"],
            "targettype": "executable",
            "mainSourceFile": "bin/ut.d",
            "dependencies": {
                "unit-threaded": "~>0.6.0"
            }
        }
    ]
}

I tried adding bin to the importpaths, but get a linker error then.

writeln

Is there a reason why writeln does not work with this library?

dub test -b unittest-cov fails on windows

The testrunner generator introduced in 0.6.3 doesn't work in combination with dub test -b unittest-cov on windows.

core.exception.AssertError@C:\Users\Bas\AppData\Roaming\dub\packages\unit-threaded-0.6.3\source\unit_threaded\should.d(160):
Expected Exception:
    source/unit_threaded/should.d:164 - Expected: 5
    source/unit_threaded/should.d:164 -      Got: 3
Got Exception:
    C:\Users\Bas\AppData\Roaming\dub\packages\unit-threaded-0.6.3\source\unit_threaded\should.d:164 - Expected: 5
    C:\Users\Bas\AppData\Roaming\dub\packages\unit-threaded-0.6.3\source\unit_threaded\should.d:164 -      Got: 3
----------------
0x00875009 in _d_assert_msg
0x0084CCF0 in @safe void unit_threaded.should.__unittestL136_45() at C:\Users\Bas\AppData\Roaming\dub\packages\unit-threaded-0.6.3\source\unit_threaded\should.d(165)
0x008535DC in void unit_threaded.should.__modtest() at C:\Users\Bas\AppData\Roaming\dub\packages\unit-threaded-0.6.3\source\unit_threaded\should.d(813)
0x0085FD1F in int unit_threaded.testsuite.moduleUnitTester().__foreachbody1(object.ModuleInfo*)

How-to mock a property

I have (simplified):

interface ICalcView {
   @property string total();
   @property void total(string t);
}
class CalcController: IController {
   private ICalcView  view;
   this(ICalcView view) {
      this.view = view;
   }

   void onClick(int number) {
      vew.total = number.to!string();
}

and, in order to test onClick:

@UnitTest
void onClick() {
   auto v = mock!ICalcView;
   v.expect!"total"("42");

   auto ctrl = new CalcController(v);
   ctrl.onClick(42);

   m.verify;
}

but dmd complains:

../../../.dub/packages/unit-threaded-0.7.7/unit-threaded/source/unit_threaded/mock.d(158,5): Error: class unit_threaded.mock.Mock!(ICalcView).Mock.MockAbstract interface function 'void total(string t) @property' is not implemented
dmd failed with exit code 1.

What is the right way to test property assignment?

Thank you

dub warning

$ cd unit-threaded/
$ dub buiild

## Warning for package unit-threaded, configuration unittest-unthreaded ##

The problem is in dub.json

             "name": "unittest-unthreaded",
             "targetType": "executable",
             "targetName": "ut_pass",
-            "dflags": ["-unittest"], //HERE
             "sourcePaths": ["tests/pass"],
             "sourceFiles": ["example/example_pass.d"],
             "mainSourceFile": "example/example_pass.d",

print execution time for all tests

I have a lot of tests that deal with file system, timeouts, etc., and if I am not careful, they can end up spending alot of time to test.

It would be very useful to print the amount of time spent per unittest in addition to the total time. This could be added as the unittests are printed on the screen. You would have to print the unittest name after the unittest is done running to make it work, else another thread could print it's stuff between the unittest name and execution time.

Would it be possible to add this? Would be very helpful

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.