Unit testing API: better mapping on JUnit, proper formatting assertion details when message is not specified

#KT-8929 Fixed
Sensible default message for assertion methods.
#KT-8314 Fixed
Provide assertFailsWith also with KClass and reified type argument.
This commit is contained in:
Ilya Gorbunov
2015-09-03 22:15:47 +03:00
parent e20c86c5dc
commit 44f7b6d699
6 changed files with 102 additions and 114 deletions
+1 -1
View File
@@ -5,5 +5,5 @@ package QUnit
*/ */
native native
public fun ok(actual: Boolean, message: String): Unit = noImpl; public fun ok(actual: Boolean, message: String?): Unit = noImpl;
+6 -18
View File
@@ -17,27 +17,15 @@ public var asserter: Asserter = QUnitAsserter()
public class QUnitAsserter(): Asserter { public class QUnitAsserter(): Asserter {
public override fun assertTrue(message: String, actual: Boolean) { public override fun assertTrue(lazyMessage: () -> String?, actual: Boolean) {
QUnit.ok(actual, lazyMessage())
}
public override fun assertTrue(message: String?, actual: Boolean) {
QUnit.ok(actual, message) QUnit.ok(actual, message)
} }
public override fun assertEquals(message: String, expected: Any?, actual: Any?) { public override fun fail(message: String?) {
QUnit.ok(expected == actual, "$message. Expected <$expected> actual <$actual>")
}
public override fun assertNotEquals(message: String, illegal: Any?, actual: Any?) {
QUnit.ok(illegal != actual, "$message. Illegal value: <$illegal>")
}
public override fun assertNotNull(message: String, actual: Any?) {
QUnit.ok(actual != null, message)
}
public override fun assertNull(message: String, actual: Any?) {
QUnit.ok(actual == null, message)
}
public override fun fail(message: String) {
QUnit.ok(false, message) QUnit.ok(false, message)
} }
} }
-15
View File
@@ -7,21 +7,6 @@ fun init() {
} }
public class JsTestsAsserter() : Asserter { public class JsTestsAsserter() : Asserter {
public override fun assertTrue(message: String, actual: Boolean) {
assert(actual, message)
}
public override fun assertEquals(message: String, expected: Any?, actual: Any?) {
assert(actual == expected, "$message. Expected <$expected> actual <$actual>")
}
public override fun assertNotEquals(message: String, illegal: Any?, actual: Any?) {
assert(illegal != actual, "$message. Illegal value: <$illegal>")
}
public override fun assertNotNull(message: String, actual: Any?) {
assert(actual != null, message)
}
public override fun assertNull(message: String, actual: Any?) {
assert(actual == null, message)
}
public override fun fail(message: String) { public override fun fail(message: String) {
assert(false, message) assert(false, message)
} }
@@ -4,27 +4,23 @@ import kotlin.test.Asserter
import org.junit.Assert import org.junit.Assert
class JUnitAsserter : Asserter { class JUnitAsserter : Asserter {
override fun assertEquals(message : String, expected : Any?, actual : Any?) { override fun assertEquals(message : String?, expected : Any?, actual : Any?) {
Assert.assertEquals(message, expected, actual) Assert.assertEquals(message, expected, actual)
} }
override fun assertNotEquals(message : String, illegal : Any?, actual : Any?) { override fun assertNotEquals(message : String?, illegal : Any?, actual : Any?) {
Assert.assertNotEquals(message, illegal, actual) Assert.assertNotEquals(message, illegal, actual)
} }
override fun assertNotNull(message : String, actual : Any?) { override fun assertNotNull(message : String?, actual : Any?) {
Assert.assertNotNull(message, actual) Assert.assertNotNull(message, actual)
} }
override fun assertNull(message : String, actual : Any?) { override fun assertNull(message : String?, actual : Any?) {
Assert.assertNull(message, actual) Assert.assertNull(message, actual)
} }
override fun assertTrue(message : String, actual : Boolean) { override fun fail(message : String?) {
Assert.assertTrue(message, actual)
}
override fun fail(message : String) {
Assert.fail(message) Assert.fail(message)
} }
} }
+60 -50
View File
@@ -3,51 +3,49 @@
*/ */
package kotlin.test package kotlin.test
/** Asserts that the given [block] returns `true`. */
public fun assertTrue(message: String, block: () -> Boolean) {
val actual = block()
asserter.assertTrue(message, actual)
}
/** Asserts that the given [block] returns `true`. */
public fun assertTrue(block: () -> Boolean): Unit = assertTrue("expected true", block)
/** Asserts that the given [block] returns `false`. */ /** Asserts that the given [block] returns `false`. */
public fun assertNot(message: String, block: () -> Boolean) { @deprecated("Use assertFalse instead.", ReplaceWith("assertFalse(message, block)"))
assertTrue(message) { !block() } public fun assertNot(message: String, block: () -> Boolean): Unit = assertFalse(message, block)
}
/** Asserts that the given [block] returns `false`. */ /** Asserts that the given [block] returns `false`. */
public fun assertNot(block: () -> Boolean): Unit = assertNot("expected false", block) @deprecated("Use assertFalse instead.", ReplaceWith("assertFalse(null, block)"))
public fun assertNot(block: () -> Boolean): Unit = assertFalse(block = block)
/** Asserts that the given [block] returns `true`. */
public fun assertTrue(message: String? = null, block: () -> Boolean): Unit = assertTrue(block(), message)
/** Asserts that the expression is `true` with an optional [message]. */ /** Asserts that the expression is `true` with an optional [message]. */
public fun assertTrue(actual: Boolean, message: String = "") { public fun assertTrue(actual: Boolean, message: String? = null) {
return assertEquals(true, actual, message) return asserter.assertTrue(message ?: "Expected value to be true.", actual)
} }
/** Asserts that the given [block] returns `false`. */
public fun assertFalse(message: String? = null, block: () -> Boolean): Unit = assertFalse(block(), message)
/** Asserts that the expression is `false` with an optional [message]. */ /** Asserts that the expression is `false` with an optional [message]. */
public fun assertFalse(actual: Boolean, message: String = "") { public fun assertFalse(actual: Boolean, message: String? = null) {
return assertEquals(false, actual, message) return asserter.assertTrue(message ?: "Expected value to be false.", !actual)
} }
/** Asserts that the [expected] value is equal to the [actual] value, with an optional [message]. */ /** Asserts that the [expected] value is equal to the [actual] value, with an optional [message]. */
public fun assertEquals(expected: Any?, actual: Any?, message: String = "") { public fun assertEquals(expected: Any?, actual: Any?, message: String? = null) {
asserter.assertEquals(message, expected, actual) asserter.assertEquals(message, expected, actual)
} }
/** Asserts that the [actual] value is not equal to the illegal value, with an optional [message]. */ /** Asserts that the [actual] value is not equal to the illegal value, with an optional [message]. */
public fun assertNotEquals(illegal: Any?, actual: Any?, message: String = "") { public fun assertNotEquals(illegal: Any?, actual: Any?, message: String? = null) {
asserter.assertNotEquals(message, illegal, actual) asserter.assertNotEquals(message, illegal, actual)
} }
/** Asserts that the [actual] value is not `null`, with an optional [message]. */ /** Asserts that the [actual] value is not `null`, with an optional [message]. */
public fun <T : Any> assertNotNull(actual: T?, message: String = ""): T { public fun <T : Any> assertNotNull(actual: T?, message: String? = null): T {
asserter.assertNotNull(message, actual) asserter.assertNotNull(message, actual)
return actual!! return actual!!
} }
/** Asserts that the [actual] value is not `null`, with an optional [message] and a function [block] to process the not-null value. */ /** Asserts that the [actual] value is not `null`, with an optional [message] and a function [block] to process the not-null value. */
public inline fun <T : Any, R> assertNotNull(actual: T?, message: String = "", block: (T) -> R) { public fun <T : Any, R> assertNotNull(actual: T?, message: String? = null, block: (T) -> R) {
asserter.assertNotNull(message, actual) asserter.assertNotNull(message, actual)
if (actual != null) { if (actual != null) {
block(actual) block(actual)
@@ -55,28 +53,30 @@ public inline fun <T : Any, R> assertNotNull(actual: T?, message: String = "", b
} }
/** Asserts that the [actual] value is `null`, with an optional [message]. */ /** Asserts that the [actual] value is `null`, with an optional [message]. */
public fun assertNull(actual: Any?, message: String = "") { public fun assertNull(actual: Any?, message: String? = null) {
asserter.assertNull(message, actual) asserter.assertNull(message, actual)
} }
/** Marks a test as having failed if this point in the execution path is reached, with an optional [message]. */ /** Marks a test as having failed if this point in the execution path is reached, with an optional [message]. */
public fun fail(message: String = "") { public fun fail(message: String? = null) {
asserter.fail(message) asserter.fail(message)
} }
/** Asserts that given function [block] returns the given [expected] value. */ /** Asserts that given function [block] returns the given [expected] value. */
public fun <T> expect(expected: T, block: () -> T) { public fun <T> expect(expected: T, block: () -> T) {
expect(expected, "expected " + expected, block) assertEquals(expected, block())
} }
/** Asserts that given function [block] returns the given [expected] value and use the given [message] if it fails. */ /** Asserts that given function [block] returns the given [expected] value and use the given [message] if it fails. */
public fun <T> expect(expected: T, message: String, block: () -> T) { public fun <T> expect(expected: T, message: String?, block: () -> T) {
val actual = block() assertEquals(expected, block(), message)
assertEquals(expected, actual, message)
} }
@deprecated("Use assertFails instead.", ReplaceWith("assertFails(block)"))
public fun fails(block: () -> Unit): Throwable? = assertFails(block)
/** Asserts that given function [block] fails by throwing an exception. */ /** Asserts that given function [block] fails by throwing an exception. */
public fun fails(block: () -> Unit): Throwable? { public fun assertFails(block: () -> Unit): Throwable? {
var thrown: Throwable? = null var thrown: Throwable? = null
try { try {
block() block()
@@ -93,15 +93,31 @@ public fun fails(block: () -> Unit): Throwable? {
* or TestNG assertion facilities. * or TestNG assertion facilities.
*/ */
public interface Asserter { public interface Asserter {
/**
* Fails the current test with the specified message.
*
* @param message the message to report.
*/
public fun fail(message: String?): Unit
/**
* Asserts that the specified value is `true`.
*
* @param lazyMessage the function to return a message to report if the assertion fails.
*/
public fun assertTrue(lazyMessage: () -> String?, actual: Boolean): Unit {
if (!actual) {
fail(lazyMessage())
}
}
/** /**
* Asserts that the specified value is `true`. * Asserts that the specified value is `true`.
* *
* @param message the message to report if the assertion fails. * @param message the message to report if the assertion fails.
*/ */
public fun assertTrue(message: String, actual: Boolean): Unit { public fun assertTrue(message: String?, actual: Boolean): Unit {
if (!actual) { assertTrue({message}, actual)
fail(message)
}
} }
/** /**
@@ -109,24 +125,17 @@ public interface Asserter {
* *
* @param message the message to report if the assertion fails. * @param message the message to report if the assertion fails.
*/ */
public fun assertEquals(message: String, expected: Any?, actual: Any?): Unit public fun assertEquals(message: String?, expected: Any?, actual: Any?): Unit {
assertTrue({ (message?.let { "$it. " } ?: "") + "Expected <$expected>, actual <$actual>." }, actual == expected)
}
/** /**
* Asserts that the specified values are not equal. * Asserts that the specified values are not equal.
* *
* @param message the message to report if the assertion fails. * @param message the message to report if the assertion fails.
*/ */
public fun assertNotEquals(message: String, illegal: Any?, actual: Any?): Unit public fun assertNotEquals(message: String?, illegal: Any?, actual: Any?): Unit {
assertTrue({ (message?.let { "$it. " } ?: "") + "Illegal value: <$actual>." }, actual != illegal)
/**
* Asserts that the specified value is not `null`.
*
* @param message the message to report if the assertion fails.
*/
public fun assertNotNull(message: String, actual: Any?): Unit {
if (actual == null) {
fail(message)
}
} }
/** /**
@@ -134,16 +143,17 @@ public interface Asserter {
* *
* @param message the message to report if the assertion fails. * @param message the message to report if the assertion fails.
*/ */
public fun assertNull(message: String, actual: Any?): Unit { public fun assertNull(message: String?, actual: Any?): Unit {
if (actual != null) { assertTrue({ (message?.let { "$it. " } ?: "") + "Expected value to be null, but was: <$actual>." }, actual == null)
fail(message)
}
} }
/** /**
* Fails the current test with the specified message. * Asserts that the specified value is not `null`.
* *
* @param message the message to report. * @param message the message to report if the assertion fails.
*/ */
public fun fail(message: String): Unit public fun assertNotNull(message: String?, actual: Any?): Unit {
assertTrue({ (message?.let { "$it. " } ?: "") + "Expected value to be not null." }, actual != null)
}
} }
+30 -21
View File
@@ -1,21 +1,40 @@
package kotlin.test package kotlin.test
import java.util.ServiceLoader import java.util.ServiceLoader
import kotlin.reflect.KClass
/** Asserts that a [block] fails with a specific exception being thrown */ @deprecated("Use assertFailsWith instead.", ReplaceWith("assertFailsWith(exceptionClass, block)"))
public fun <T: Throwable> failsWith(exceptionClass: Class<T>, block: ()-> Any): T { public fun <T: Throwable> failsWith(exceptionClass: Class<T>, block: ()-> Any): T = assertFailsWith(exceptionClass, { block() })
/** Asserts that a [block] fails with a specific exception being thrown. */
public fun <T: Throwable> assertFailsWith(exceptionClass: Class<T>, block: () -> Unit): T = assertFailsWith(exceptionClass, null, block)
/** Asserts that a [block] fails with a specific exception being thrown. */
public fun <T: Throwable> assertFailsWith(exceptionClass: Class<T>, message: String?, block: () -> Unit): T {
try { try {
block() block()
asserter.fail("Expected an exception to be thrown") }
throw IllegalStateException("Should have failed") catch (e: Throwable) {
} catch (e: T) {
if (exceptionClass.isInstance(e)) { if (exceptionClass.isInstance(e)) {
return e return e as T
} }
asserter.fail((message?.let { "$it. "} ?: "") + "Expected an exception of type $exceptionClass to be thrown, but was $e")
throw e throw e
} }
val msg = message?.let { "$it. " } ?: ""
asserter.fail(msg + "Expected an exception of type $exceptionClass to be thrown, but was completed successfully.")
throw IllegalStateException(msg + "Should have failed.")
} }
/** Asserts that a [block] fails with a specific exception of type [exceptionClass] being thrown. */
public fun <T: Throwable> assertFailsWith(exceptionClass: KClass<T>, message: String? = null, block: () -> Unit): T = assertFailsWith(exceptionClass.java, message, block)
/** Asserts that a [block] fails with a specific exception of type [T] being thrown.
* Since inline method doesn't allow to trace where it was invoked, it is required to pass a [message] to distinguish this method call from others.
*/
public inline fun <reified T: Throwable> assertFailsWith(message: String, @noinline block: () -> Unit): T = assertFailsWith(T::class.java, message, block)
/** /**
* Comments out a [block] of test code until it is implemented while keeping a link to the code * Comments out a [block] of test code until it is implemented while keeping a link to the code
* to implement in your unit test output * to implement in your unit test output
@@ -51,20 +70,10 @@ public var asserter: Asserter
*/ */
private class DefaultAsserter() : Asserter { private class DefaultAsserter() : Asserter {
public override fun assertEquals(message : String, expected : Any?, actual : Any?) { public override fun fail(message : String?) {
if (expected != actual) { if (message == null)
fail("$message. Expected <$expected> actual <$actual>") throw AssertionError()
} else
} throw AssertionError(message)
override fun assertNotEquals(message : String, illegal: Any?, actual : Any?) {
if (illegal == actual) {
fail("$message. Illegal value: <$illegal>")
}
}
public override fun fail(message : String) {
throw AssertionError(message)
} }
} }