package asunit.framework {
import asunit.errors.AssertionFailedError;
import flash.utils.getQualifiedClassName;
import flash.errors.IllegalOperationError;
import flash.events.EventDispatcher;
/**
* A set of assert methods. Messages are only displayed when an assert fails.
*/
public class Assert extends EventDispatcher {
/**
* Protect constructor since it is a static only class
*/
public function Assert() {
}
/**
* Asserts that a condition is true. If it isn't it throws
* an AssertionFailedError with the given message.
*/
static public function assertTrue(...args:Array):void {
var message:String;
var actual:Object;
if(args.length == 1) {
message = "";
actual = args[0];
}
else if(args.length == 2) {
message = args[0];
actual = args[1];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(!actual) {
throw new AssertionFailedError(format(message, true, actual));
}
}
/**
* Asserts that a condition is false. If it isn't it throws
* an AssertionFailedError with the given message.
*/
static public function assertFalse(...args:Array):void {
var message:String;
var actual:Object;
if(args.length == 1) {
message = "";
actual = args[0];
}
else if(args.length == 2) {
message = args[0];
actual = args[1];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(actual) {
throw new AssertionFailedError(format(message, false, actual));
}
}
/**
* Fails a test with the given message.
*
* @example This method can be called anytime you want to break out and fail
* the current test.
*
*
* public function testSomething():void {
* var instance:MyClass = new MyClass();
* if(instance.foo()) {
* fail('The foo should not have been there');
* }
* }
*
*/
static public function fail(message:String):void {
throw new AssertionFailedError(message);
}
/**
* Asserts that the provided block throws an exception that matches
* the type provided.
*
*
* public function testFailingCode():void {
* assertThrows(CustomError, function():void {
* var instance:Sprite = new Sprite();
* instance.callMethodThatThrows();
* });
* }
*
**/
static public function assertThrows(errorType:Class, block:Function):void {
try {
block.call();
}
catch(e:Error) {
if(!(e is errorType)) {
throw new AssertionFailedError("expected error type:<" + getQualifiedClassName(errorType)
+"> but was:<" + getQualifiedClassName(e) + ">");
}
return;
}
throw new AssertionFailedError("expected error type:<" + getQualifiedClassName(errorType) + "> but none was thrown." );
}
/**
* Asserts that two objects are equal. If they are not
* an AssertionFailedError is thrown with the given message.
*
* This assertion should be (by far) the one you use the most.
* It automatically provides useful information about what
* the failing values were.
*
*
* public function testNames():void {
* var name1:String = "Federico Aubele";
* var name2:String = "Frederico Aubele";
*
* assertEquals(name1, name2);
* }
*
*/
static public function assertEquals(...args:Array):void {
var message:String;
var expected:Object;
var actual:Object;
if(args.length == 2) {
message = "";
expected = args[0];
actual = args[1];
}
else if(args.length == 3) {
message = args[0];
expected = args[1];
actual = args[2];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(expected == null && actual == null) {
return;
}
try {
if(expected != null && expected.equals(actual)) {
return;
}
}
catch(e:Error) {
if(expected != null && expected == actual) {
return;
}
}
throw new AssertionFailedError(format(message, expected, actual));
}
/**
* Asserts that an object isn't null. If it is
* an AssertionFailedError is thrown with the given message.
*/
static public function assertNotNull(...args:Array):void {
var message:String;
var actual:Object;
if(args.length == 1) {
message = "";
actual = args[0];
}
else if(args.length == 2) {
message = args[0] + " ";
actual = args[1];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(actual == null) {
throw new AssertionFailedError(message + "expected not null but was:<" + actual + ">");
}
}
/**
* Asserts that an object is null. If it is not
* an AssertionFailedError is thrown with the given message.
*/
static public function assertNull(...args:Array):void {
var message:String;
var actual:Object;
if(args.length == 1) {
message = "";
actual = args[0];
}
else if(args.length == 2) {
message = args[0];
actual = args[1];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(actual != null) {
throw new AssertionFailedError(format(message, null, actual));
}
}
/**
* Asserts that two objects refer to the same object. If they are not
* an AssertionFailedError is thrown with the given message.
*/
static public function assertSame(...args:Array):void {
var message:String;
var expected:Object;
var actual:Object;
if(args.length == 2) {
message = "";
expected = args[0];
actual = args[1];
}
else if(args.length == 3) {
message = args[0] + " ";
expected = args[1];
actual = args[2];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(expected !== actual) {
throw new AssertionFailedError(message + "expected same as:<" + expected + "> but was:<" + actual + ">");
}
}
/**
* Asserts that two objects do not refer to the same object. If they do,
* an AssertionFailedError is thrown with the given message.
*/
static public function assertNotSame(...args:Array):void {
var message:String;
var expected:Object;
var actual:Object;
if(args.length == 2) {
message = "";
expected = args[0];
actual = args[1];
}
else if(args.length == 3) {
message = args[0] + " ";
expected = args[1];
actual = args[2];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if(expected === actual) {
throw new AssertionFailedError(message + "expected not same but both were:<" + actual + ">");
}
}
/**
* Asserts that two numerical values are equal within a tolerance range.
* If they are not an AssertionFailedError is thrown with the given message.
*/
static public function assertEqualsFloat(...args:Array):void {
var message:String;
var expected:Number;
var actual:Number;
var tolerance:Number = 0;
if(args.length == 3) {
message = "";
expected = args[0];
actual = args[1];
tolerance = args[2];
}
else if(args.length == 4) {
message = args[0];
expected = args[1];
actual = args[2];
tolerance = args[3];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if (isNaN(tolerance)) tolerance = 0;
if(Math.abs(expected - actual) <= tolerance) {
return;
}
throw new AssertionFailedError(format(message, expected, actual));
}
/**
* Asserts that two arrays have the same length and contain the same
* objects in the same order. If the arrays are not equal by this
* definition an AssertionFailedError is thrown with the given message.
*/
static public function assertEqualsArrays(...args:Array):void {
var message:String;
var expected:Array;
var actual:Array;
if(args.length == 2) {
message = "";
expected = args[0];
actual = args[1];
}
else if(args.length == 3) {
message = args[0];
expected = args[1];
actual = args[2];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if (expected == null && actual == null) {
return;
}
if ((expected == null && actual != null) || (expected != null && actual == null)) {
failNotEquals(message, expected, actual);
}
// from here on: expected != null && actual != null
if (expected.length != actual.length) {
failNotEquals(message, expected, actual);
}
for (var i : int = 0; i < expected.length; i++) {
assertEquals(expected[i], actual[i]);
}
}
/**
* Asserts that two arrays have the same length and contain the same
* objects. The order of the objects in the arrays is ignored. If they
* are not equal by this definition an AssertionFailedError is thrown
* with the given message.
*/
static public function assertEqualsArraysIgnoringOrder(...args:Array):void {
var message:String;
var expected:Array;
var actual:Array;
if(args.length == 2) {
message = "";
expected = args[0];
actual = args[1];
}
else if(args.length == 3) {
message = args[0];
expected = args[1];
actual = args[2];
}
else {
throw new IllegalOperationError("Invalid argument count");
}
if (expected == null && actual == null) {
return;
}
if ((expected == null && actual != null) || (expected != null && actual == null)) {
failNotEquals(message, expected, actual);
}
// from here on: expected != null && actual != null
if (expected.length != actual.length) {
failNotEquals(message, expected, actual);
}
for (var i : int = 0; i < expected.length; i++) {
var foundMatch : Boolean = false;
var expectedMember : Object = expected[i];
for (var j : int = 0; j < actual.length; j++) {
var actualMember : Object = actual[j];
try {
assertEquals(expectedMember, actualMember);
foundMatch = true;
break;
}
catch (e : AssertionFailedError) {
// no match, try next
}
}
if (!foundMatch) {
failNotEquals("Found no match for " + expectedMember + ";", expected, actual);
}
}
}
static private function failNotEquals(message:String, expected:Object, actual:Object):void {
fail(format(message, expected, actual));
}
static private function format(message:String, expected:Object, actual:Object):String {
var formatted:String = "";
if(message != null) {
formatted = message + " ";
}
return formatted + "expected:<" + expected + "> but was:<" + actual + ">";
}
}
}