Giter Site home page Giter Site logo

utest's Introduction

utest

utest is an easy to use unit testing library for Haxe. It works on all the supported platforms including nodejs.

Installation

Install is as easy as:

haxelib install utest

Basic usage

In your main method define the minimal instances needed to run your tests.

import utest.Runner;
import utest.ui.Report;

class TestAll {
  public static function main() {
    //the long way
    var runner = new Runner();
    runner.addCase(new TestCase1());
    runner.addCase(new TestCase2());
    Report.create(runner);
    runner.run();

    //the short way in case you don't need to handle any specifics
    utest.UTest.run([new TestCase1(), new TestCase2()]);
  }
}

TestCase must extend utest.Test or implement utest.ITest.

TestCase needs to follow some conventions:

  • Every test case method name must be prefixed with test or spec;
  • If a method is prefixed with spec it is treated as the specification test. Every boolean binary operation will be wrapped in Assert.isTrue()

Following methods could be implemented to setup or teardown:

/**
 * This method is executed once before running the first test in the current class.
 * If it accepts an argument, it is treated as an asynchronous method.
 */
function setupClass():Void;
function setupClass(async:Async):Void;
/**
 * This method is executed before each test.
  * If it accepts an argument, it is treated as an asynchronous method.
 */
function setup():Void;
function setup(async:Async):Void;
/**
 * This method is executed after each test.
  * If it accepts an argument, it is treated as an asynchronous method.
 */
function teardown():Void;
function teardown(async:Async):Void;
/**
 * This method is executed once after the last test in the current class is finished.
  * If it accepts an argument, it is treated as an asynchronous method.
 */
function teardownClass():Void;
function teardownClass(async:Async):Void;

Default timeout for asynchronous methods is 250ms. You can change it by adding @:timeout(500) meta.

To add all test cases from my.pack package use runner.addCases(my.pack). Any module found in my.pack is treated as a test case. That means each module should contain a class implementing utest.ITest and that class should have the same name as the module name.

import utest.Assert;
import utest.Async;

class TestCase extends utest.Test {
  var field:String;

  //synchronous setup
  public function setup() {
    field = "some";
  }

  function testFieldIsSome() {
    Assert.equals("some", field);
  }

  function specField() {
    field.charAt(0) == 's';
    field.length > 3;
  }

  //asynchronous teardown
  @:timeout(700) //default timeout is 250ms
  public function teardown(async:Async) {
    field = null; // not really needed

    //simulate asynchronous teardown
    haxe.Timer.delay(
      function() {
        //resolve asynchronous action
        async.done();
      },
      500
    );
  }
}

Ignore a test

To skip certain test or test case one can annotate them with @:ignore meta. The meta accpets an optional string argument to indicate the reason ignoring the test.

class TestCase1 extends utest.Test {
  @:ignore
  function testSomethingNotReadyYet() {
    //this test will not be executed
  }
}

@:ignore('The functionality under test is not ready yet')
class TestCase2 extends utest.Test {
  function testSomething {
    //this test will not be executed
  }

  function testOtherThing {
    //this test will not be executed
  }
}

Inter-test dependencies

It is possible to define how tests depend on each other with @:depends meta:

class TestCase extends utest.Test {

	function testBasicThing1() {
		//...
	}

	function testBasicThing2() {
		//...
	}


	@:depends(testBasicThing, testBasicThing2)
	function testComplexThing() {
		//...
	}
}

In this example testComplexThing will be executed only if testBasicThing1 and testBasicThing2 pass.

Dependencies between test classes

@:depends meta could also be used to define dependencies of one class with tests on other classes with tests.

package some.pack;

class TestCase1 extends utest.Test {
	function test1() {
		//...
	}
}

@:depends(some.pack.TestCase1)
class TestCase2 extends utest.Test {
	function test2() {
		//...
	}
}

In this example tests from some.pack.TestCase2 will be executed only if there were no failures in some.pack.TestCase1.

Ignore dependencies

If for some reason you want to run a test regardless the outcome of the tests it depends on, you can use -D UTEST_IGNORE_DEPENDS define or set an environment variable with the same name.

Running single test from a test suite.

Adding -D UTEST_PATTERN=pattern to the compilation flags makes UTest to run only tests which have names matching the pattern. The pattern could be a plain string or a regular expression without delimiters.

Another option is to add UTEST_PATTERN to the environment variables at compile time.

Async tests

If a test case accepts an argument, that test case is treated as an asynchronous test.

@:timeout(500) //change timeout (default: 250ms)
function testSomething(async:utest.Async) {
  // do your async goodness and remember to call `done()` at the end.
  haxe.Timer.delay(function() {
    Assert.isTrue(true); // put a sensible test here
    async.done();
  }, 50);
}

It's also possible to "branch" asynchronous tests. In this case a test will be considered completed when all branches are finished.

function testSomething(async:utest.Async) {
  var branch = async.branch();
  haxe.Timer.delay(function() {
    Assert.isTrue(true); // put a sensible test here
    branch.done();
  }, 50);

  // or create an asynchronous branch with a callback
  async.branch(function(branch) {
    haxe.Timer.delay(function() {
      Assert.isTrue(true); // put a sensible test here
      branch.done();
    }, 50);
  });
}

Print test names being executed

-D UTEST_PRINT_TESTS makes UTest print test names in the process of tests execution. The output will look like this:

Running my.tests.TestAsync...
    testSetTimeout
    testTimeout
Running my.tests.TestAnother...
    testThis
    testThat

And after finishing all the tests UTest will print usual report.

Another option is to add UTEST_PRINT_TESTS to the environment variables at compile time.

Convert failures into exceptions

It is possible to make UTest throw an unhandled exception instead of adding a failure to the report.

Enable this behavior with -D UTEST_FAILURE_THROW, or by adding UTEST_FAILURE_THROW to the environment variables at compile time.

In this case any exception or failure in test or setup methods will lead to a crash. Instead of a test report you will see an unhandled exception message with the exception stack trace (depending on a target platform).

Assert

Assert contains a plethora of methods to perform your tests:

isTrue(cond:Bool, ?msg:String, ?pos:PosInfos)

Asserts successfully when the condition is true.

cond The condition to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

isFalse(value:Bool, ?msg:String, ?pos:PosInfos)

Asserts successfully when the condition is false.

cond The condition to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

isNull(value:Dynamic, ?msg:String, ?pos:PosInfos)

Asserts successfully when the value is null.

value The value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

notNull(value:Dynamic, ?msg:String, ?pos:PosInfos)

Asserts successfully when the value is not null.

value The value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

is(value:Dynamic, type:Dynamic, ?msg:String , ?pos:PosInfos)

Asserts successfully when the 'value' parameter is of the of the passed type 'type'.

value The value to test

type The type to test against

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

notEquals(expected:Dynamic, value:Dynamic, ?msg:String , ?pos:PosInfos)

Asserts successfully when the value parameter is not the same as the expected one.

Assert.notEquals(10, age);

expected The expected value to check against

value The value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

equals(expected:Dynamic, value:Dynamic, ?msg:String , ?pos:PosInfos)

Asserts successfully when the value parameter is equal to the expected one.

Assert.equals(10, age);

expected The expected value to check against

value The value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

match(pattern:EReg, value:Dynamic, ?msg:String , ?pos:PosInfos)

Asserts successfully when the value parameter does match against the passed EReg instance.

Assert.match(~/x/i, "Haxe");

pattern The pattern to match against

value The value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

floatEquals(expected:Float, value:Float, ?approx:Float, ?msg:String , ?pos:PosInfos)

Same as Assert.equals but considering an approximation error.

Assert.floatEquals(Math.PI, value);

expected The expected value to check against

value The value to test

approx The approximation tollerance. Default is 1e-5

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

same(expected:Dynamic, value:Dynamic, ?recursive:Bool, ?msg:String, ?pos:PosInfos)

Check that value is an object with the same fields and values found in expected. The default behavior is to check nested objects in fields recursively.

Assert.same({ name:"utest"}, ob);

expected The expected value to check against

value The value to test

recursive States whether or not the test will apply also to sub-objects. Defaults to true

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

raises(method:Void -> Void, ?type:Class<Dynamic>, ?msgNotThrown:String , ?msgWrongType:String, ?pos:PosInfos)

It is used to test an application that under certain circumstances must react throwing an error. This assert guarantees that the error is of the correct type (or Dynamic if non is specified).

Assert.raises(function() { throw "Error!"; }, String);

method A method that generates the exception.

type The type of the expected error. Defaults to Dynamic (catch all).

msgNotThrown An optional error message used when the function fails to raise the expected exception. If not passed a default one will be used

msgWrongType An optional error message used when the function raises the exception but it is of a different type than the one expected. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing. @todo test the optional type parameter

allows<T>(possibilities:Array<T>, value:T, ?msg:String , ?pos:PosInfos)

Checks that the test value matches at least one of the possibilities.

possibility An array of possible matches

value The value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

contains<T>(match:T, values:Array<T>, ?msg:String , ?pos:PosInfos)

Checks that the test array contains the match parameter.

match The element that must be included in the tested array

values The values to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

notContains<T>(match:T, values:Array<T>, ?msg:String , ?pos:PosInfos)

Checks that the test array does not contain the match parameter.

match The element that must NOT be included in the tested array

values The values to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

stringContains(match:String, value:String, ?msg:String , ?pos:PosInfos)

Checks that the expected values is contained in value.

match the string value that must be contained in value

value the value to test

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it

fail(msg = "failure expected", ?pos:PosInfos)

Forces a failure.

msg An optional error message. If not passed a default one will be used

pos Code position where the Assert call has been executed. Don't fill it unless you know what you are doing.

warn(msg)

Creates a warning message.

msg A mandatory message that justifies the warning.

pos Code position where the Assert call has been executed. Don't fill it

utest's People

Contributors

alexhaxe avatar andyli avatar andywhite37 avatar aurel300 avatar cedx avatar fantoine avatar fponticelli avatar frederisk avatar gama11 avatar jdonaldson avatar jonasmalacofilho avatar joshtynjala avatar maniues avatar mlms13 avatar mrtraan avatar ncbray avatar player-03 avatar profelis avatar realyuniquename avatar romanmikhailov avatar sebthom avatar simn avatar t1ml3arn avatar tong avatar wighawag 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

utest's Issues

Release a new version for Haxe 4.1.0

After upgrading from Haxe 4.0.5 to v4.1.0, a lot of deprecation warnings appeared when running the tests of a JS project:

utest/1,10,1/src/utest/ui/Report.hx:28: characters 16-22 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/HtmlReport.hx:452: characters 16-22 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/HtmlReport.hx:453: characters 15-21 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/HtmlReport.hx:725: characters 51-57 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/HtmlReport.hx:726: characters 37-43 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/HtmlReport.hx:729: characters 15-21 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/PlainTextReport.hx:163: characters 16-22 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/PlainTextReport.hx:164: characters 15-21 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/PlainTextReport.hx:165: characters 16-22 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/ui/text/PlainTextReport.hx:166: characters 15-21 : Warning : __js__ is deprecated, use js.Syntax.code instead
utest/1,10,1/src/utest/utils/Print.hx:8: characters 12-18 : Warning : __js__ is deprecated, use js.Syntax.code instead

I know that these deprecations were fixed in 30a0f02, so it would be cool if a new package version was released to address this issue.

Also: the url field of the haxelib.json file should point to this repository. I almost posted this issue in the wrong place.

Multiple async calls

In haxe-sys tests I use the following setup:

https://github.com/Aurel300/haxe-sys/blob/f3b24404315a83f390513ad44d03023f8237074e/tests/test/Test.hx#L12-L38

Then in tests:

function testSomething(async:Async) {
  sub(async, done -> {
    // ...
    somethingAsynchronous(() -> done());
  });
  sub(async, done -> {
    differentAsynchronousThing(() -> done());
  });
}

This is convenient when doing performing multiple asynchronous tasks, which may finish at different times, but are either connected (e.g. a client + server test), or at least related (convenient to place them under a single "test"). It counts how many calls to done are expected and how many calls actually arrive.

Could there be a similar API accessible on Async directly?

Add a global mechanism for filtering which tests are run

Sometimes I just want to run a single test to debug something without running other tests.

Runner .addCase lets you specify a pattern per test class. Maybe runner could also let you specify a global pattern that overrides all other patterns, like runner.setPattern(~/testMyTest/).

Or, each test function could have a @:only metadata, and if there are any functions with @:only, the runner only runs those?

Runner#addCases by package does not filter duplicates

I occasionally specify class paths arguments -cp twice and receive failed tests related to latest Runner#addCases functionality.

> haxe -cp src -cp test -cp test -main TestAll -D utest -D exit -D unsafe -dce std -debug -cs bin/test-cs
> mono --debug bin/test-cs/bin/TestAll-Debug.exe
results: SOME TESTS FAILURES (success: false)
utest.TestRunner
  testAddCases_identifier: FAILURE F
    line: 21, expected 3 but it is 6
  testAddCases_notRecursive: FAILURE F
    line: 9, expected 2 but it is 4
  testAddCases_recursive: FAILURE F
    line: 15, expected 3 but it is 6

I think there should be duplicates filtering inside.
@RealyUniqueName What do you think?

async on setup

hello @fponticelli ,
i was testing some stuff with zombie.js (https://github.com/assaf/zombie/blob/master/README.md)
i get the Assert.createAsync stuff but i would like to know if it's possible to do some async setup.

function setup(p):Void
{
zombie = new Zombie();

     //Zombie.localhost("localhost",8888);
    // untyped zombie.dump();
     done = Assert.createAsync();
     zombie.visit("http://localhost:8888/index.php",function(e){

        // make here a call to testAsync1, testAsync2 etc...

        done();
    }
    );

}

public function testAsync1(){

        Assert.equals("poupidou",zombie.text("p"));     

}
public function testAsync2(){

        Assert.equals("poupidou",zombie.text("p"));     

}

Do you get what i mean ?
thx

htmlReport doesn't work on php target..

targetting php ( haxe rc1 fail) other targets works fine.
testcase as simple as that ..:

import utest.Runner;
import utest.ui.Report;

class RunAll {
	static public function main() {
		trace("runAll");

		var runner = new Runner();
		// runner.addCase(new TestMots());

		Report.create(runner); // breaks
		// new utest.ui.text.PrintReport(runner); //ok
                //new utest.ui.text.HtmlReport(runner, true);//breaks

		runner.run();
	}
}

.

as3 target is broken

HaxeFoundation/haxe#7901 (comment)
and

/home/travis/build/Simn/haxe/tests/unit/bin/as3/utest/ITestHandler.as(103): col: 31 Error: Incompatible override.
		protected override function bindHandler() : void {

This is some Haxe problem related to the @:public metadata being added by can_access. However, after fixing that there are some more problems. It would be good if we could find a way to dodge this in utest.

(quote from HaxeFoundation/haxe#7901 (comment))

Class name pattern

UTEST_PATTERN only filters tests based on function name. For the spec tests in Haxe, this is a problem, since the generated tests only differ in class names.

Maybe there should be a UTEST_CLASS_PATTERN ?

Tests should return true/false

I have a lot of tests that cascade, so it doesn't make sense to test if the first test fails. I do a lot of parameterized testing so the additional failures create a lot of noise when the test fails.

Right now I must basically test the condition first, save it to a variable, and then run isTrue for every test. It would be ideal if the tests just returned true/false to indicate passing, which I could save to a variable and use as a conditional later.

[rant] Runner.addCases is a trap

So you can use addCase to add an individual case, cool. Naturally, you'd expect its plural version, addCases, to add multiple cases. Probably accepting an array as argument, right?

But it does something completely different. It's actually a macro which does something with package paths. The problem here is that runner.addCases(classes) type-checks without a problem, it just won't do anything unless you happen to have a classes package somewhere.

I don't really know why I'm opening this issue.

Attempt to call a nil value error on Lua

Hey, I am trying to run tests for the lua target, and I am getting the following error:

 lua: build/lua/test.lua:1106: attempt to call a nil value (method 'lastIndexOf')
 stack traceback:
 	build/lua/test.lua:1106: in field 'startsWith'
 	build/lua/test.lua:8435: in method 'isTestFixtureName'
 	build/lua/test.lua:8361: in method 'addITest'
 	build/lua/test.lua:8343: in method 'addCase'
 	build/lua/test.lua:1198: in field 'main'
 	build/lua/test.lua:10096: in main chunk
 	[C]: in ?

The same tests run fine with the rest of the targets, cpp, neko, hl, js etc.

The full build: https://gitlab.com/haath/bytetype/-/jobs/578696044

The tests folder in question: https://gitlab.com/haath/bytetype/-/tree/master/test

Simple way to print out running tests

To make utest print out which test (class and method) is going to be run before it is started, I use:

runner.onTestStart.add(test -> trace("running", test.fixture.target, test.fixture.method));

This is very helpful when debugging code that can completely crash the process e.g. by segfaulting. The line itself is simple enough, but I think it would be nice if this was a built-in feature, either enabled with a define like -D UTEST_PRINT_TESTS or a field on the runner like runner.printTestNames = true;.

No test result message on cpp target

When I run a test on cpp with something like this .hxml:

-cp hscript
-cp plus/test
-lib utest
-main TestAll
-cpp plus/bin/test-cpp

-cmd start plus/bin/test-cpp/TestAll.exe

I got nothing at all. Maybe just a warning from $type().
I hardly found some .hxml targetting cpp on the internet.

Float as Int

Hi,

I hit another hiccup with Assert.same and it is because the way Haxe own Type.typeOf works for Number (at least in js):
https://github.com/HaxeFoundation/haxe/blob/development/std/js/_std/Type.hx#L157

I basically have a json file as test data and it contains float (like 6.0)
It is then parsed using -D HaxeJson and have a value of 6

Then in same it check type first using Type.typeof which return TInt in that case. it then use the int equality as opposed to the expected float equality

I hope that make sense

I am not sure where the error lies here. We could argue that Type.typeOf should never return TInt in js as in js there is no Int but it would be weird to have a variable typed as Int returning Float?

Would there be a way to get arround that issue in utest ?

Maybe by considerring int and float similarly (at least for Assert.same) ?

What do you think?

Haxe < 4.1 compatibility

Has support for Haxe < 4.1 been dropped? Was it intentional? 😃

Screenshot from 2020-07-24 16-03-00

P.S. Some of these failures may be from tooling issues, but it's definitively broken on 3.4.7 (and possibly 4.0.5).
P.P.S. This popped up on the record-macros tests.

Add expect

Should take something like this:

expect(x + y == 3);

And transform into:

var t1 = x,
    t2 = y
    t3 = x + y;
Assert.isTrue(t3 == 3, 'expected `x <$t1> + y <$t2> == 3 <$t3>`');

Not sure if expect should be part of Assert or specific to utest tests.

Null safety

Enable null safety for utest package and test suite.

Make NeverShowSuccessResults the default?

The output can get quite verbose with lots of classes, which makes it impractical to not use report.displaySuccessResults = NeverShowSuccessResults. Shouldn't this be the default? I can't imagine why anyone would want to look at hundreds of OK ... lines.

Catchable assertion failures

It would be nice if we had an option to raise assertion failures as real exceptions so they can be caught when debugging. We can do this through a -D flag or some other way.

Readability of Assert.same output with arrays

It looks like Assert.same is quite smart for structures and outputs something quite readable:

line: 23, expected 14 but it is 15 for field range.start.character

Unfortunately, this stops working when the arguments are wrapped in arrays:

line: 24, expected array element at [0] to be {kind: 2, severity: 1, range: {start: {line: 2, character: 14}, end: {line: 2, character: 15}}, args: Expected type parameter} but it is {kind: 2, severity: 1, range: {start: {line: 2, character: 15}, end: {line: 2, character: 16}}, args: Expected type parameter} for field array[0].range.start.character

import utest.Test;
import utest.UTest;
import utest.Assert;

class Main extends Test {
	static function main() {
		UTest.run([new Main()]);
	}

	function test() {
		var a = {
			kind: 2,
			severity: 1,
			range: {start: {line: 2, character: 14}, end: {line: 2, character: 15}},
			args: "Expected type parameter"
		};
		var b = {
			kind: 2,
			severity: 1,
			range: {start: {line: 2, character: 15}, end: {line: 2, character: 16}},
			args: "Expected type parameter"
		};
		Assert.same(a, b);
		Assert.same([a], [b]);
	}
}

UTest.run(cases, callback): callback not called

The callback parameter is added too late to Runner.onComplete. It's currently added after the Report is created, but it should be added before.

// Bad: trace not displayed.
UTest.run([], () -> trace("callback not called"));

// Bad: trace not displayed.
final runner = new Runner();
Report.create(runner);
runner.onComplete.add(_ -> trace("callback not called"));
runner.run();

// Good: trace is displayed.
final runner = new Runner();
runner.onComplete.add(_ -> trace("callback called"));
Report.create(runner);
runner.run();

This is probably due to the fact that the created Report is an instance of PlainTextReport, and that this class calls Sys.exit() in its complete function.

delay for closing swf

hello franco!
i just tried utest today ..
it could be useful to set delay in PlainTextReport as a variable...
5 seconds is a bit short ... :)
personnaly i did

if(flash.system.Security.sandboxType == "localTrusted") {
var delay = Runner.delay;
trace('all done, exiting in $delay seconds');
haxe.Timer.delay(function() try {
flash.system.System.exit(result.stats.isOk ? 0 : 1);
} catch(e : Dynamic) {
// do nothing
}, delay * 1000);
}

Async setup & Suite setup

Hi,

I'm using utest for a nodejs project and I would like to be able to implement async suite setups.

I already simulated a 'suite setup' by counting each call to setup and calling a custom setupSuite method on first setup call.

However I have some trouble to get my async setup call.
I have some async database manipulations to run on my setupSuite and use Assert.createAsync to try to 'lock' the call to the tests, but it doesn't seem to work.

Is there a way to achieve this?

Assert.notSame()

I noticed that there's a not-version of most Assert methods, but not same(). Any reason for that?

API to expose test results

Currently, there is no way to access test results.
Something like this is needed:

public var success(default,null):Bool;
public getFailures():FailuresData;

maybe as an addition to utest.ui.common.IReport

Requested here:

#if js
	static function nodejsMain() {
		main();
		(untyped process).exit(Test.success ? 0 : 1);
	}
	#end

I couldn't immediately find how to get the success state of the tests.
(quote from HaxeFoundation/haxe#7901 (comment))

Add `utest.Async.setTimeout(ms)`

It would be nice to have a way to set the timeout without using @:timeout meta, such as async.setTimeout(ms). This would be useful in case the test methods were created by a build macro - you can't just add @:timeout from a build macro because utest's build macro might run first.

Perhaps @:timeout on class level would also make sense, to allow setting a default for all tests in a class.

Cannot build documentation - syntax error for java

I've got this error while trying to build documentation (by hxml from doc/ fodler)

C:\HaxeToolkit\utest/git/src/utest/ui/text/HtmlReport.hx:712: characters 4-7 : Type not found : Lib
Error: Command failed with error 1

Seems java target there is an unnecessary one, cause java.Lib does not have print() method

function _handler(report : HtmlReport) {
#if (php || neko || cpp || java || lua)
Lib.print(report.getHtml());
#elseif js

Should java be removed or replaced with trace() or similar?

utest for Haxe 3 ?

Hi Franco,
this is Yannick from SilexLabs, how do you do ?

I'm upgrading cocktail to Haxe 3 and I use utest, it doesn't seem available on haxelib. Do you plan to release it at some point ?

I tried to make it work from your repo, it builds but it don't seem to run.

Thanks for the great work

Assert is not compatible with null safety

Looks like various Assert methods need to be wrapped in Null<T>:

import utest.Assert;

@:nullSafety
function main() {
	Assert.equals(null, null);
}
source/Main.hx:5: characters 16-20 : Null safety: Cannot pass nullable value to not-nullable argument "expected" of function "equals".
source/Main.hx:5: characters 22-26 : Null safety: Cannot pass nullable value to not-nullable argument "value" of function "equals".

Assert.isNull(null); not working is particularly funny... :D

js fails to exit properly on travis

I got TypeError: undefined is not a function (evaluating 'process.exit(result.stats.isOk ? 0 : 1)') when running js tests with travis (using the lib travix) with -D travis (utest version 1.8.1)

I believe that maybe in PlainTextReport.hx line 163 we should also check that process.exit is not undefined? Or check phantom first?

Here the full output:

$ haxelib run travix js
phantomjs-update.5
installPackage-build-essential.5
> sudo apt-get update -qq
W: http://ppa.launchpad.net/couchdb/stable/ubuntu/dists/trusty/Release.gpg: Signature by key 15866BAFD9BCC4F3C1E0DFC7D69548E1C17EAB57 uses weak digest algorithm (SHA1)
> sudo apt-get install --no-install-recommends -qq build-essential
installPackage-chrpath.5
> sudo apt-get install --no-install-recommends -qq chrpath
Selecting previously unselected package chrpath.
(Reading database ... 97798 files and directories currently installed.)
Preparing to unpack .../chrpath_0.14-3ubuntu1_amd64.deb ...
Unpacking chrpath (0.14-3ubuntu1) ...
Processing triggers for man-db (2.6.7.1-1ubuntu1) ...
Setting up chrpath (0.14-3ubuntu1) ...
installPackage-libfontconfig1.5
> sudo apt-get install --no-install-recommends -qq libfontconfig1
installPackage-libfontconfig1-dev.5
> sudo apt-get install --no-install-recommends -qq libfontconfig1-dev
installPackage-libfreetype6.5
> sudo apt-get install --no-install-recommends -qq libfreetype6
installPackage-libfreetype6-dev.5
> sudo apt-get install --no-install-recommends -qq libfreetype6-dev
installPackage-libssl-dev.5
> sudo apt-get install --no-install-recommends -qq libssl-dev
Preconfiguring packages ...
(Reading database ... 97806 files and directories currently installed.)
Preparing to unpack .../libssl-dev_1.0.1f-1ubuntu2.26_amd64.deb ...
Unpacking libssl-dev:amd64 (1.0.1f-1ubuntu2.26) over (1.0.1f-1ubuntu2.23) ...
Preparing to unpack .../libssl1.0.0_1.0.1f-1ubuntu2.26_amd64.deb ...
Unpacking libssl1.0.0:amd64 (1.0.1f-1ubuntu2.26) over (1.0.1f-1ubuntu2.23) ...
Setting up libssl1.0.0:amd64 (1.0.1f-1ubuntu2.26) ...
Setting up libssl-dev:amd64 (1.0.1f-1ubuntu2.26) ...
Processing triggers for libc-bin (2.19-0ubuntu6.13) ...
installPackage-libxft-dev.5
> sudo apt-get install --no-install-recommends -qq libxft-dev
> wget https://github.com/Medium/phantomjs/releases/download/v2.1.1/phantomjs-2.1.1-linux-x86_64.tar.bz2
--2018-08-29 11:22:08--  https://github.com/Medium/phantomjs/releases/download/v2.1.1/phantomjs-2.1.1-linux-x86_64.tar.bz2
Resolving github.com (github.com)... 192.30.253.113, 192.30.253.112
Connecting to github.com (github.com)|192.30.253.113|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://github-production-release-asset-2e65be.s3.amazonaws.com/5755891/d55faeca-f27c-11e5-84be-6e92fb868e05?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20180829%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180829T112208Z&X-Amz-Expires=300&X-Amz-Signature=55dc46fd76c3237fdeff4294ecce4985796b98347df11e12dd3d17a8efe01a67&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dphantomjs-2.1.1-linux-x86_64.tar.bz2&response-content-type=application%2Foctet-stream [following]
--2018-08-29 11:22:08--  https://github-production-release-asset-2e65be.s3.amazonaws.com/5755891/d55faeca-f27c-11e5-84be-6e92fb868e05?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20180829%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180829T112208Z&X-Amz-Expires=300&X-Amz-Signature=55dc46fd76c3237fdeff4294ecce4985796b98347df11e12dd3d17a8efe01a67&X-Amz-SignedHeaders=host&actor_id=0&response-content-disposition=attachment%3B%20filename%3Dphantomjs-2.1.1-linux-x86_64.tar.bz2&response-content-type=application%2Foctet-stream
Resolving github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)... 52.216.162.219
Connecting to github-production-release-asset-2e65be.s3.amazonaws.com (github-production-release-asset-2e65be.s3.amazonaws.com)|52.216.162.219|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 23415665 (22M) [application/octet-stream]
Saving to: ‘phantomjs-2.1.1-linux-x86_64.tar.bz2’
100%[======================================>] 23,415,665  5.81MB/s   in 4.6s   
2018-08-29 11:22:13 (4.85 MB/s) - ‘phantomjs-2.1.1-linux-x86_64.tar.bz2’ saved [23415665/23415665]
> tar xvjf phantomjs-2.1.1-linux-x86_64.tar.bz2
phantomjs-2.1.1-linux-x86_64/
phantomjs-2.1.1-linux-x86_64/examples/
phantomjs-2.1.1-linux-x86_64/examples/colorwheel.js
phantomjs-2.1.1-linux-x86_64/examples/scandir.js
phantomjs-2.1.1-linux-x86_64/examples/page_events.js
phantomjs-2.1.1-linux-x86_64/examples/loadspeed.js
phantomjs-2.1.1-linux-x86_64/examples/injectme.js
phantomjs-2.1.1-linux-x86_64/examples/render_multi_url.js
phantomjs-2.1.1-linux-x86_64/examples/server.js
phantomjs-2.1.1-linux-x86_64/examples/netlog.js
phantomjs-2.1.1-linux-x86_64/examples/pagecallback.js
phantomjs-2.1.1-linux-x86_64/examples/module.js
phantomjs-2.1.1-linux-x86_64/examples/arguments.js
phantomjs-2.1.1-linux-x86_64/examples/universe.js
phantomjs-2.1.1-linux-x86_64/examples/openurlwithproxy.js
phantomjs-2.1.1-linux-x86_64/examples/sleepsort.js
phantomjs-2.1.1-linux-x86_64/examples/modernizr.js
phantomjs-2.1.1-linux-x86_64/examples/unrandomize.js
phantomjs-2.1.1-linux-x86_64/examples/hello.js
phantomjs-2.1.1-linux-x86_64/examples/stdin-stdout-stderr.js
phantomjs-2.1.1-linux-x86_64/examples/fibo.js
phantomjs-2.1.1-linux-x86_64/examples/phantomwebintro.js
phantomjs-2.1.1-linux-x86_64/examples/echoToFile.js
phantomjs-2.1.1-linux-x86_64/examples/post.js
phantomjs-2.1.1-linux-x86_64/examples/loadurlwithoutcss.js
phantomjs-2.1.1-linux-x86_64/examples/child_process-examples.js
phantomjs-2.1.1-linux-x86_64/examples/printenv.js
phantomjs-2.1.1-linux-x86_64/examples/useragent.js
phantomjs-2.1.1-linux-x86_64/examples/rasterize.js
phantomjs-2.1.1-linux-x86_64/examples/outputEncoding.js
phantomjs-2.1.1-linux-x86_64/examples/waitfor.js
phantomjs-2.1.1-linux-x86_64/examples/serverkeepalive.js
phantomjs-2.1.1-linux-x86_64/examples/postserver.js
phantomjs-2.1.1-linux-x86_64/examples/printmargins.js
phantomjs-2.1.1-linux-x86_64/examples/version.js
phantomjs-2.1.1-linux-x86_64/examples/run-qunit.js
phantomjs-2.1.1-linux-x86_64/examples/features.js
phantomjs-2.1.1-linux-x86_64/examples/netsniff.js
phantomjs-2.1.1-linux-x86_64/examples/walk_through_frames.js
phantomjs-2.1.1-linux-x86_64/examples/printheaderfooter.js
phantomjs-2.1.1-linux-x86_64/examples/responsive-screenshot.js
phantomjs-2.1.1-linux-x86_64/examples/countdown.js
phantomjs-2.1.1-linux-x86_64/examples/detectsniff.js
phantomjs-2.1.1-linux-x86_64/examples/simpleserver.js
phantomjs-2.1.1-linux-x86_64/examples/postjson.js
phantomjs-2.1.1-linux-x86_64/examples/run-jasmine2.js
phantomjs-2.1.1-linux-x86_64/examples/run-jasmine.js
phantomjs-2.1.1-linux-x86_64/README.md
phantomjs-2.1.1-linux-x86_64/LICENSE.BSD
phantomjs-2.1.1-linux-x86_64/bin/
phantomjs-2.1.1-linux-x86_64/bin/phantomjs
phantomjs-2.1.1-linux-x86_64/third-party.txt
phantomjs-2.1.1-linux-x86_64/ChangeLog
build-js.5
> haxe -js bin/js/tests.js -lib travix -lib yield tests.hxml
Warning : This case is unused
Warning : This case is unused
Warning : This case is unused
Warning : This case is unused
Warning : This case is unused
Warning : This case is unused
> phantomjs-2.1.1-linux-x86_64/bin/phantomjs -v
2.1.1
> phantomjs-2.1.1-linux-x86_64/bin/phantomjs --web-security=no bin/js/runPhantom.js
PrintReport.hx:52: 
assertations: 787
successes: 787
errors: 0
failures: 0
warnings: 0
execution time: 0.053
results: ALL TESTS OK (success: true)
TypeError: undefined is not a function (evaluating 'process.exit(result.stats.isOk ? 0 : 1)')

[Discussion] `Runner.addCase` pattern seems to be inconsistent.

Question related to patterns in Runner.addCase.

Why Runner.addCase function argument pattern doesn't override globalPattern?

https://github.com/fponticelli/utest/blob/master/src/utest/Runner.hx#L102

It will be more logical that more narrow declaration override more global declaration, not vice versa, isn't it?

Should this condition be rewrited as if (pattern == null) pattern = globalPattern;?

As for me globalPattern should have global policy, meanwhile pattern in addCase should allow to change global behavior.

@fponticelli What do you think?

utest vs. static "test"

If you have a test class with a static function that has "test" in its name, utest "kind of" picks it up and ends up causing errors:

class Main implements utest.ITest {
	static public function main() {
		utest.UTest.run([new Main()]);
	}

	function new() {}

	static function test() {}
}

source/Main.hx:8: characters 2-27 : Cannot access static field test from a class instance

I think it should ignore statics.

[js] uncaught exception: invalid duplicated fixture

I've got this error

uncaught exception: invalid duplicated fixture: TestCase.testFoo

Code to reproduce

import utest.*;
import utest.ui.*;

class Main {
    static function main() {
        var runner = new Runner();
        runner.addCase(new TestCase());
        Report.create(runner);
        runner.run();
    }
}

@:keep
class TestCase{
    public function new() {}

    public function testFoo(){
        Assert.isTrue(true);
        Assert.isFalse(false);
        Assert.fail('A');    // without this fail()
        Assert.warn("WARNING"); // and without this warn() there is no error
    }
}

build.hxml file

-cp src
-lib utest
-dce std
-D analyzer-optimize
-main Main
-js bin/out.js
# --interp

Tested on both haxe version 3.4.2 and 3.4.7
utest version is 1.8.0

Some notes

Exception throws if there is Assert.warn() or Assert.fail(). With no those all is perfect.
dce and analyzer-optimize have no affect on result. If we replace js target on interp there is also no error.

This issue can be related to this #52 due the same error.

Looks like for several targets reports are not very accurate.

Look at output of latest self-tests running:
https://travis-ci.org/haxe-utest/utest/jobs/318686593

Reports are different for different targets.
I think it can impact also on execution of async tests.

Compare neko and nodejs:

assertations: 54
successes: 54
errors: 0
failures: 0
warnings: 0
execution time: 0.027
results: ALL TESTS OK (success: true)
assertations: 55
successes: 55
errors: 0
failures: 0
warnings: 0
execution time: 0.131
results: ALL TESTS OK (success: true)

I think it can be caused by difference in running on these targets:
https://github.com/haxe-utest/utest/blob/master/src/utest/Runner.hx#L182

considerations for v2

Breaking Changes

Assert.createAsync

It will be removed, and replaced by more flexible signatures of tests cases:

class Test {
  @:timeout(500) // defaults to 200ms
  public function testAsync(done : Void -> Void) {
    // make sure to invoke done() at the end of the test
  }

  public function testPromise() : Promise<Nil> { ... }
  public function testFuture() : Future<Nil> { ... }
}

New Features

Analyze Test Classes at compile time

runner.registerClass(Test); // no need to instantiate Test

asynchronous setup/teardown

Same features as standard tests

add setupInstance/teardownInstance

Add setup/teardown that run once per instance instead of once per method.

annotations

@:timeout(time)

Set the acceptable timeout for test methods

@:setup/setupInstance

Marks a method as a setup method

@:teardown/teardownInstance

Marks a method as a teardown method

@:test(?description)

Marks a method as a test case

@:spec

Marks a method as a spec test. A spec test takes all the == (and other comparison operators) and transform them into asserts.

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.