Skip to content

Commit

Permalink
Assert.raisesCondition (closes #107, closes #121)
Browse files Browse the repository at this point in the history
  • Loading branch information
RealyUniqueName committed Dec 14, 2023
1 parent 43244ea commit 22e869a
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
- Minimum supported Haxe version is 4.1 now.
- added `Assert.similar()` (see the doc to that method)
- changed various `Assert` methods to be type safe instead of accepting `Dynamic` arguments
- added `Assert.raisesCondition`
- added UTEST_IGNORE_DEPENDS flag to ignore failed or missing dependencies (see README.md)
- added test case name filter to `Runner.addCases`
- support @:ignore meta (old @Ignored meta is still supported too)
Expand Down
50 changes: 48 additions & 2 deletions src/utest/Assert.hx
Original file line number Diff line number Diff line change
Expand Up @@ -666,14 +666,60 @@ class Assert {
* unless you know what you are doing.
*/
public static function raises(method:() -> Void, ?type:Any, ?msgNotThrown : String , ?msgWrongType : String, ?pos : PosInfos) : Bool {
var typeDescr = type == null ? "" : "of type " + Type.getClassName(type);
return _raisesImpl(method, type, _ -> true, msgNotThrown, msgWrongType, pos);
}

/**
* It is used to test an application that under certain circumstances must
* react throwing an error with specific characteristics checked in the `condition` callback.
* Simple condition check example:
* ```haxe
* Assert.raisesCondition(() -> throw new MyException('Hello, world!'), MyException, e -> e.message.indexOf('Hello') == 0);
* ```
* Complex condition check example:
* ```haxe
* Assert.raisesCondition(
* () -> throw new MyException('Hello, world!'),
* MyException, e -> {
* Assert.equals(e.code, 10);
* Assert.isTrue(e.message.length > 5);
* }
* );
* ```
* @param method A method that generates the exception.
* @param type The type of the expected error.
* @param condition The callback which is called upon an exception of expected type. The assertion passes
* if this callback returns `true`. Otherwise assertion fails.
* @param msgNotThrown An optional error message used when the function fails to raise the expected
* exception. If not passed a default one will be used.
* @param 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.
* @param msgWrongCondition An optional error message used when the `condition` callback returns `false`
* @param pos Code position where the Assert call has been executed. Don't fill it
* unless you know what you are doing.
*/
public static function raisesCondition<T>(method:() -> Void, type:Class<T>, condition:(e:T)->Bool, ?msgNotThrown : String , ?msgWrongType : String, ?msgWrongCondition : String, ?pos : PosInfos) : Bool {
var cond = e -> {
if(null == msgWrongCondition)
msgWrongCondition = 'exception of ${Type.getClassName(type)} is raised, but condition failed';
isTrue(condition(e), msgWrongCondition, pos);
}
return _raisesImpl(method, type, cond, msgNotThrown, msgWrongType, pos);
}

static function _raisesImpl(method:() -> Void, type:Any, condition : (Dynamic)->Bool, msgNotThrown : String , msgWrongType : String, pos : PosInfos) {
var typeDescr = "of type " + Type.getClassName(type);
inline function handleCatch(ex:Any):Bool {
return if(null == type) {
pass(pos);
} else {
if (null == msgWrongType)
msgWrongType = "expected throw " + typeDescr + " but it is " + ex;
isTrue(Std.isOfType(ex, type), msgWrongType, pos);
if(isTrue(Std.isOfType(ex, type), msgWrongType, pos)) {
condition(ex);
} else {
false;
}
}
}
try {
Expand Down
8 changes: 7 additions & 1 deletion test/utest/TestAssert.hx
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ class TestAssert extends Test {
//expect specific exception type
var errors : Array<Any> = ["str", 1, 0.1, new TestAssert(), {}, [1], new SampleException('sample exception')];
var types : Array<Any> = [String, Int, Float, TestAssert, Dynamic, Array, SampleException];
var expectedsuccess = 14;
for(errorIndex => error in errors)
for(typeIndex => type in types) {
if(errorIndex == typeIndex || type == Dynamic || (Std.isOfType(error, Int) && type == Float)) {
Expand All @@ -107,6 +106,13 @@ class TestAssert extends Test {
}
}

public function testRaisesCondition() {
success(() -> raisesCondition(() -> throw new SampleException('haxe.Exception-based'), SampleException, e -> e.message.indexOf('haxe') >= 0));
failure(() -> raisesCondition(() -> throw new SampleException('haxe.Exception-based'), SampleException, e -> e.message == 'fail'));
success(() -> raisesCondition(() -> throw 'Non-haxe.Exception', String, e -> e.indexOf('haxe') >= 0));
failure(() -> raisesCondition(() -> throw 'Non-haxe.Exception', String, e -> e == 'fail'));
}

public function testIs() {
var values : Array<Any> = ["str", 1, 0.1, new TestAssert(), {}, [1]];
var types : Array<Any> = [String, Int, Float, TestAssert, Dynamic, Array];
Expand Down

0 comments on commit 22e869a

Please sign in to comment.