@@ -2,17 +2,19 @@ package alphaTab.core
22
33import alphaTab.SnapshotFileRepository
44import alphaTab.TestPlatformPartials
5+ import alphaTab.collections.List
56import alphaTab.collections.ObjectDoubleMap
67import org.junit.Assert
78import java.lang.reflect.Method
89import java.nio.file.Paths
910import kotlin.contracts.ExperimentalContracts
1011import kotlin.reflect.KClass
1112
13+ annotation class TestClass (val name : String )
1214annotation class TestName (val name : String )
1315annotation class SnapshotFile (val path : String )
1416
15- typealias Test = org.junit. Test
17+
1618
1719class assert {
1820 companion object {
@@ -50,6 +52,7 @@ class NotExpector<T>(private val actual: T) {
5052class Expector <T >(private val actual : T ) {
5153 val to
5254 get() = this
55+
5356 fun not () = NotExpector (actual)
5457
5558 val be
@@ -69,8 +72,9 @@ class Expector<T>(private val actual: T) {
6972 expectedTyped = expected.toInt();
7073 }
7174
72- if (expected is Double && expected == 0.0 &&
73- actualToCheck is Double ) {
75+ if (expected is Double && expected == 0.0 &&
76+ actualToCheck is Double
77+ ) {
7478 val d = actualToCheck as Double ;
7579 if (d == - 0.0 ) {
7680 @Suppress(" UNCHECKED_CAST" )
@@ -84,7 +88,10 @@ class Expector<T>(private val actual: T) {
8488
8589 fun lessThan (expected : Double ) {
8690 if (actual is Number ) {
87- Assert .assertTrue(" Expected $actual to be less than $expected " , actual.toDouble() < expected)
91+ Assert .assertTrue(
92+ " Expected $actual to be less than $expected " ,
93+ actual.toDouble() < expected
94+ )
8895 } else {
8996 Assert .fail(" lessThan can only be used with numeric operands" );
9097 }
@@ -93,11 +100,15 @@ class Expector<T>(private val actual: T) {
93100
94101 fun greaterThan (expected : Double ) {
95102 if (actual is Number ) {
96- Assert .assertTrue(" Expected $actual to be greater than $expected " , actual.toDouble() > expected)
103+ Assert .assertTrue(
104+ " Expected $actual to be greater than $expected " ,
105+ actual.toDouble() > expected
106+ )
97107 } else {
98108 Assert .fail(" greaterThan can only be used with numeric operands" );
99109 }
100110 }
111+
101112 fun closeTo (expected : Double , delta : Double , message : String? = null) {
102113 if (actual is Number ) {
103114 Assert .assertEquals(message, expected, actual.toDouble(), delta)
@@ -106,21 +117,24 @@ class Expector<T>(private val actual: T) {
106117 }
107118 }
108119
109- fun length (expected : Double ) {
110- if (actual is alphaTab.collections.List <* >) {
120+ fun length (expected : Double ) {
121+ if (actual is alphaTab.collections.List <* >) {
111122 Assert .assertEquals(expected.toInt(), actual.length.toInt())
112- } else if (actual is alphaTab.collections.DoubleList ) {
123+ } else if (actual is alphaTab.collections.DoubleList ) {
113124 Assert .assertEquals(expected.toInt(), actual.length.toInt())
114- } else if (actual is alphaTab.collections.BooleanList ) {
125+ } else if (actual is alphaTab.collections.BooleanList ) {
115126 Assert .assertEquals(expected.toInt(), actual.length.toInt())
116127 } else {
117128 Assert .fail(" length can only be used with collection operands" );
118129 }
119130 }
120131
121132 fun contain (value : Any ) {
122- if (actual is Iterable <* >) {
123- Assert .assertTrue(" Expected collection ${actual.joinToString(" ," )} to contain $value " , actual.contains(value))
133+ if (actual is Iterable <* >) {
134+ Assert .assertTrue(
135+ " Expected collection ${actual.joinToString(" ," )} to contain $value " ,
136+ actual.contains(value)
137+ )
124138 } else {
125139 Assert .fail(" contain can only be used with Iterable operands" );
126140 }
@@ -180,15 +194,15 @@ class Expector<T>(private val actual: T) {
180194
181195 private fun findTestMethod (): Method {
182196 val walker = StackWalker .getInstance(StackWalker .Option .RETAIN_CLASS_REFERENCE )
183- var testMethod: Method ? = null
197+ var testMethod: Method ? = null
184198 walker.forEach { frame ->
185- if (testMethod == null ) {
199+ if (testMethod == null ) {
186200 val method = frame.declaringClass.getDeclaredMethod(
187201 frame.methodName,
188202 * frame.methodType.parameterArray()
189203 )
190204
191- if (method.getAnnotation(Test ::class .java) != null ) {
205+ if (method.getAnnotation(org.junit. Test ::class .java) != null ) {
192206 testMethod = method
193207 }
194208 }
@@ -203,7 +217,7 @@ class Expector<T>(private val actual: T) {
203217
204218 @ExperimentalUnsignedTypes
205219 @ExperimentalContracts
206- fun toMatchSnapshot () {
220+ fun toMatchSnapshot (hint : String = "" ) {
207221 val testMethodInfo = findTestMethod()
208222 val file = testMethodInfo.getAnnotation(SnapshotFile ::class .java)?.path
209223 if (file.isNullOrEmpty()) {
@@ -218,23 +232,35 @@ class Expector<T>(private val actual: T) {
218232 Assert .fail(" Could not find snapshot file at $absoluteSnapFilePath " )
219233 }
220234
221- val snapshotFile = SnapshotFileRepository .loadSnapshortFile (absoluteSnapFilePath.toString())
235+ val snapshotFile = SnapshotFileRepository .loadSnapshotFile (absoluteSnapFilePath.toString())
222236
223- val testSuiteName = testMethodInfo.declaringClass.simpleName
237+ val parts = List <String >();
238+ collectTestSuiteNames(parts, testMethodInfo.declaringClass)
224239 val testName = testMethodInfo.getAnnotation(TestName ::class .java)!! .name
240+ parts.push(testName)
241+
242+ val snapshotName = TestGlobals .useSnapshotValue(parts.joinToString(" " ), hint);
243+
244+
225245
226- val fullTestName = " $testSuiteName $testName "
227246
228- val counter = (TestGlobals .snapshotAssertionCounters.get(fullTestName) ? : 0.0 ) + 1
229- TestGlobals .snapshotAssertionCounters.set(fullTestName, counter)
230247
231- val snapshotName = " $fullTestName${counter.toInt()} "
232248
233249 val error = snapshotFile.match(snapshotName, actual)
234250 if (! error.isNullOrEmpty()) {
235251 Assert .fail(error)
236252 }
237253 }
254+
255+ private fun collectTestSuiteNames (parts : List <String >, testClass : Class <* >) {
256+ if (testClass.declaringClass != null ) {
257+ collectTestSuiteNames(parts, testClass.declaringClass!! );
258+ }
259+
260+ val testSuiteName =
261+ testClass.getAnnotation(TestClass ::class .java)?.name ? : testClass.simpleName
262+ parts.push(testSuiteName);
263+ }
238264}
239265
240266class TestGlobals {
@@ -243,6 +269,18 @@ class TestGlobals {
243269 companion object {
244270 val snapshotAssertionCounters: ObjectDoubleMap <String > = ObjectDoubleMap ()
245271
272+ fun useSnapshotValue (baseName : String , hint : String ): String {
273+ var fullName = baseName
274+ if (hint.isNotEmpty()) {
275+ fullName + = " : $hint " ;
276+ }
277+
278+ val value =
279+ if (snapshotAssertionCounters.has(fullName)) snapshotAssertionCounters.get(fullName)!! + 1 else 1.0
280+ snapshotAssertionCounters.set(fullName, value)
281+ return " $fullName ${value.toInt()} " ;
282+ }
283+
246284 fun <T > expect (actual : T ): Expector <T > {
247285 return Expector (actual);
248286 }
0 commit comments