Skip to content

Commit 6971453

Browse files
committed
Add unit tests for core plugin components
Tests cover: - TestoClasses: attribute arrays content, no overlaps, constants - TestoTestDescriptor: isTestClassName logic - TestoVersionDetector: version parsing, error handling - TestoFrameworkType: constants, ID, composer packages - TestoRunnerSettings: defaults, custom values, fromPhpTestRunnerSettings - TestoRunConfigurationHandler: config file option, singleton - MixinExtensions: takeWhileInclusive for sequences and collections - LineMarkerCompanion: RUNNABLE_ATTRIBUTES composition - PsiUtil: MEANINGFUL_ATTRIBUTES composition, no duplicates https://claude.ai/code/session_01TmFvjfMtoxTvddQRBzsbPN
1 parent c32af9a commit 6971453

9 files changed

Lines changed: 355 additions & 0 deletions
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.github.xepozz.testo
2+
3+
import junit.framework.TestCase
4+
5+
class MixinExtensionsTest : TestCase() {
6+
7+
fun testTakeWhileInclusive_sequence_stopsAfterFalse() {
8+
val result = sequenceOf(1, 2, 3, 4, 5).takeWhileInclusive { it < 3 }.toList()
9+
assertEquals(listOf(1, 2, 3), result)
10+
}
11+
12+
fun testTakeWhileInclusive_sequence_allTrue() {
13+
val result = sequenceOf(1, 2, 3).takeWhileInclusive { it < 10 }.toList()
14+
assertEquals(listOf(1, 2, 3), result)
15+
}
16+
17+
fun testTakeWhileInclusive_sequence_firstFalse() {
18+
val result = sequenceOf(5, 1, 2).takeWhileInclusive { it < 3 }.toList()
19+
assertEquals(listOf(5), result)
20+
}
21+
22+
fun testTakeWhileInclusive_sequence_empty() {
23+
val result = emptySequence<Int>().takeWhileInclusive { it < 3 }.toList()
24+
assertEquals(emptyList<Int>(), result)
25+
}
26+
27+
fun testTakeWhileInclusive_collection_stopsAfterFalse() {
28+
val result = listOf(1, 2, 3, 4, 5).takeWhileInclusive { it < 3 }
29+
assertEquals(listOf(1, 2, 3), result.toList())
30+
}
31+
32+
fun testTakeWhileInclusive_collection_allTrue() {
33+
val result = listOf(1, 2).takeWhileInclusive { it < 10 }
34+
assertEquals(listOf(1, 2), result.toList())
35+
}
36+
37+
fun testTakeWhileInclusive_collection_empty() {
38+
val result = emptyList<Int>().takeWhileInclusive { it < 3 }
39+
assertTrue(result.isEmpty())
40+
}
41+
42+
fun testTakeWhileInclusive_collection_singleElement_true() {
43+
val result = listOf(1).takeWhileInclusive { it < 3 }
44+
assertEquals(listOf(1), result.toList())
45+
}
46+
47+
fun testTakeWhileInclusive_collection_singleElement_false() {
48+
val result = listOf(10).takeWhileInclusive { it < 3 }
49+
assertEquals(listOf(10), result.toList())
50+
}
51+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.util.PsiUtil
4+
import junit.framework.TestCase
5+
6+
class PsiUtilTest : TestCase() {
7+
8+
fun testMeaningfulAttributes_containsAllGroups() {
9+
val meaningful = PsiUtil.MEANINGFUL_ATTRIBUTES.toSet()
10+
11+
for (attr in TestoClasses.DATA_ATTRIBUTES) {
12+
assertTrue("Missing data attribute: $attr", meaningful.contains(attr))
13+
}
14+
for (attr in TestoClasses.TEST_ATTRIBUTES) {
15+
assertTrue("Missing test attribute: $attr", meaningful.contains(attr))
16+
}
17+
for (attr in TestoClasses.TEST_INLINE_ATTRIBUTES) {
18+
assertTrue("Missing inline test attribute: $attr", meaningful.contains(attr))
19+
}
20+
for (attr in TestoClasses.BENCH_ATTRIBUTES) {
21+
assertTrue("Missing bench attribute: $attr", meaningful.contains(attr))
22+
}
23+
}
24+
25+
fun testMeaningfulAttributes_totalCount() {
26+
val expected = TestoClasses.DATA_ATTRIBUTES.size +
27+
TestoClasses.TEST_ATTRIBUTES.size +
28+
TestoClasses.TEST_INLINE_ATTRIBUTES.size +
29+
TestoClasses.BENCH_ATTRIBUTES.size
30+
assertEquals(expected, PsiUtil.MEANINGFUL_ATTRIBUTES.size)
31+
}
32+
33+
fun testMeaningfulAttributes_noDuplicates() {
34+
val attrs = PsiUtil.MEANINGFUL_ATTRIBUTES
35+
assertEquals(attrs.size, attrs.toSet().size)
36+
}
37+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.github.xepozz.testo
2+
3+
import junit.framework.TestCase
4+
5+
class TestoClassesTest : TestCase() {
6+
7+
fun testTestAttributes_containsExpectedValues() {
8+
val attrs = TestoClasses.TEST_ATTRIBUTES
9+
assertEquals(2, attrs.size)
10+
assertTrue(attrs.contains("\\Testo\\Attribute\\Test"))
11+
assertTrue(attrs.contains("\\Testo\\Application\\Attribute\\Test"))
12+
}
13+
14+
fun testTestInlineAttributes_containsExpectedValues() {
15+
val attrs = TestoClasses.TEST_INLINE_ATTRIBUTES
16+
assertEquals(2, attrs.size)
17+
assertTrue(attrs.contains("\\Testo\\Sample\\TestInline"))
18+
assertTrue(attrs.contains("\\Testo\\Inline\\TestInline"))
19+
}
20+
21+
fun testDataAttributes_containsAllDataTypes() {
22+
val attrs = TestoClasses.DATA_ATTRIBUTES
23+
assertEquals(7, attrs.size)
24+
assertTrue(attrs.contains("\\Testo\\Sample\\DataProvider"))
25+
assertTrue(attrs.contains("\\Testo\\Data\\DataProvider"))
26+
assertTrue(attrs.contains("\\Testo\\Sample\\DataSet"))
27+
assertTrue(attrs.contains("\\Testo\\Data\\DataSet"))
28+
assertTrue(attrs.contains("\\Testo\\Data\\DataUnion"))
29+
assertTrue(attrs.contains("\\Testo\\Data\\DataCross"))
30+
assertTrue(attrs.contains("\\Testo\\Data\\DataZip"))
31+
}
32+
33+
fun testBenchAttributes_containsExpectedValues() {
34+
val attrs = TestoClasses.BENCH_ATTRIBUTES
35+
assertEquals(1, attrs.size)
36+
assertTrue(attrs.contains("\\Testo\\Bench\\BenchWith"))
37+
}
38+
39+
fun testConstants_assertionException() {
40+
assertEquals("\\Testo\\Assert\\State\\Assertion\\AssertionException", TestoClasses.ASSERTION_EXCEPTION)
41+
}
42+
43+
fun testConstants_assert() {
44+
assertEquals("\\Testo\\Assert", TestoClasses.ASSERT)
45+
}
46+
47+
fun testConstants_expect() {
48+
assertEquals("\\Testo\\Expect", TestoClasses.EXPECT)
49+
}
50+
51+
fun testDataAttributes_noOverlapWithTestAttributes() {
52+
val dataSet = TestoClasses.DATA_ATTRIBUTES.toSet()
53+
val testSet = TestoClasses.TEST_ATTRIBUTES.toSet()
54+
val inlineSet = TestoClasses.TEST_INLINE_ATTRIBUTES.toSet()
55+
val benchSet = TestoClasses.BENCH_ATTRIBUTES.toSet()
56+
57+
assertTrue(dataSet.intersect(testSet).isEmpty())
58+
assertTrue(dataSet.intersect(inlineSet).isEmpty())
59+
assertTrue(dataSet.intersect(benchSet).isEmpty())
60+
assertTrue(testSet.intersect(inlineSet).isEmpty())
61+
assertTrue(testSet.intersect(benchSet).isEmpty())
62+
assertTrue(inlineSet.intersect(benchSet).isEmpty())
63+
}
64+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.tests.TestoFrameworkType
4+
import junit.framework.TestCase
5+
6+
class TestoFrameworkTypeTest : TestCase() {
7+
8+
fun testConstants() {
9+
assertEquals("Testo", TestoFrameworkType.ID)
10+
assertEquals("php_qn", TestoFrameworkType.SCHEMA)
11+
}
12+
13+
fun testGetID() {
14+
val type = TestoFrameworkType()
15+
assertEquals("Testo", type.id)
16+
}
17+
18+
fun testComposerPackageNames() {
19+
val type = TestoFrameworkType()
20+
val packages = type.composerPackageNames
21+
assertTrue(packages.contains("php"))
22+
}
23+
24+
fun testGetDescriptor() {
25+
val type = TestoFrameworkType()
26+
assertNotNull(type.descriptor)
27+
}
28+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.tests.TestoTestRunLineMarkerProvider
4+
import junit.framework.TestCase
5+
6+
class TestoLineMarkerCompanionTest : TestCase() {
7+
8+
fun testRunnableAttributes_containsAllDataAttributes() {
9+
val runnable = TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.toSet()
10+
for (attr in TestoClasses.DATA_ATTRIBUTES) {
11+
assertTrue("Missing data attribute: $attr", runnable.contains(attr))
12+
}
13+
}
14+
15+
fun testRunnableAttributes_containsInlineTestAttributes() {
16+
val runnable = TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.toSet()
17+
for (attr in TestoClasses.TEST_INLINE_ATTRIBUTES) {
18+
assertTrue("Missing inline test attribute: $attr", runnable.contains(attr))
19+
}
20+
}
21+
22+
fun testRunnableAttributes_containsBenchAttributes() {
23+
val runnable = TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.toSet()
24+
for (attr in TestoClasses.BENCH_ATTRIBUTES) {
25+
assertTrue("Missing bench attribute: $attr", runnable.contains(attr))
26+
}
27+
}
28+
29+
fun testRunnableAttributes_doesNotContainPlainTestAttributes() {
30+
val runnable = TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.toSet()
31+
for (attr in TestoClasses.TEST_ATTRIBUTES) {
32+
assertFalse("Should not contain plain test attribute: $attr", runnable.contains(attr))
33+
}
34+
}
35+
36+
fun testRunnableAttributes_totalCount() {
37+
val expected = TestoClasses.DATA_ATTRIBUTES.size +
38+
TestoClasses.TEST_INLINE_ATTRIBUTES.size +
39+
TestoClasses.BENCH_ATTRIBUTES.size
40+
assertEquals(expected, TestoTestRunLineMarkerProvider.RUNNABLE_ATTRIBUTES.size)
41+
}
42+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.tests.run.TestoRunConfigurationHandler
4+
import junit.framework.TestCase
5+
6+
class TestoRunConfigurationHandlerTest : TestCase() {
7+
8+
fun testGetConfigFileOption() {
9+
assertEquals("--config", TestoRunConfigurationHandler.INSTANCE.configFileOption)
10+
}
11+
12+
fun testSingletonInstance() {
13+
assertSame(TestoRunConfigurationHandler.INSTANCE, TestoRunConfigurationHandler.INSTANCE)
14+
}
15+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.tests.run.TestoRunnerSettings
4+
import com.jetbrains.php.testFramework.run.PhpTestRunnerSettings
5+
import junit.framework.TestCase
6+
7+
class TestoRunnerSettingsTest : TestCase() {
8+
9+
fun testDefaults() {
10+
val settings = TestoRunnerSettings()
11+
assertEquals(-1, settings.dataProviderIndex)
12+
assertEquals(-1, settings.dataSetIndex)
13+
assertFalse(settings.parallelTestingEnabled)
14+
}
15+
16+
fun testCustomValues() {
17+
val settings = TestoRunnerSettings(
18+
dataProviderIndex = 3,
19+
dataSetIndex = 5,
20+
parallelTestingEnabled = true,
21+
)
22+
assertEquals(3, settings.dataProviderIndex)
23+
assertEquals(5, settings.dataSetIndex)
24+
assertTrue(settings.parallelTestingEnabled)
25+
}
26+
27+
fun testFromPhpTestRunnerSettings() {
28+
val base = PhpTestRunnerSettings()
29+
base.scope = PhpTestRunnerSettings.Scope.File
30+
base.filePath = "/some/path/TestFile.php"
31+
base.methodName = "testSomething"
32+
base.directoryPath = "/some/dir"
33+
base.isUseAlternativeConfigurationFile = true
34+
base.configurationFilePath = "/config/testo.xml"
35+
base.testRunnerOptions = "--verbose"
36+
37+
val result = TestoRunnerSettings.fromPhpTestRunnerSettings(base)
38+
39+
assertEquals(PhpTestRunnerSettings.Scope.File, result.scope)
40+
assertEquals("/some/path/TestFile.php", result.filePath)
41+
assertEquals("testSomething", result.methodName)
42+
assertEquals("/some/dir", result.directoryPath)
43+
assertTrue(result.isUseAlternativeConfigurationFile)
44+
assertEquals("/config/testo.xml", result.configurationFilePath)
45+
assertEquals("--verbose", result.testRunnerOptions)
46+
// Testo-specific fields should be defaults
47+
assertEquals(-1, result.dataProviderIndex)
48+
assertEquals(-1, result.dataSetIndex)
49+
assertFalse(result.parallelTestingEnabled)
50+
}
51+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.tests.TestoTestDescriptor
4+
import junit.framework.TestCase
5+
6+
class TestoTestDescriptorTest : TestCase() {
7+
8+
fun testIsTestClassName_withTestSuffix() {
9+
assertTrue(TestoTestDescriptor.isTestClassName("UserTest"))
10+
assertTrue(TestoTestDescriptor.isTestClassName("SomeFeatureTest"))
11+
}
12+
13+
fun testIsTestClassName_withTestBaseSuffix() {
14+
assertTrue(TestoTestDescriptor.isTestClassName("AbstractTestBase"))
15+
assertTrue(TestoTestDescriptor.isTestClassName("BaseFeatureTestBase"))
16+
}
17+
18+
fun testIsTestClassName_withoutTestSuffix() {
19+
assertFalse(TestoTestDescriptor.isTestClassName("UserService"))
20+
assertFalse(TestoTestDescriptor.isTestClassName("TestHelper"))
21+
assertFalse(TestoTestDescriptor.isTestClassName("Testing"))
22+
assertFalse(TestoTestDescriptor.isTestClassName("Contest"))
23+
}
24+
25+
fun testIsTestClassName_edgeCases() {
26+
assertTrue(TestoTestDescriptor.isTestClassName("Test"))
27+
assertTrue(TestoTestDescriptor.isTestClassName("TestBase"))
28+
assertFalse(TestoTestDescriptor.isTestClassName(""))
29+
}
30+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.github.xepozz.testo
2+
3+
import com.github.xepozz.testo.tests.TestoVersionDetector
4+
import com.intellij.execution.ExecutionException
5+
import junit.framework.TestCase
6+
7+
class TestoVersionDetectorTest : TestCase() {
8+
9+
fun testParse_validVersion() {
10+
assertEquals("1.0.0", TestoVersionDetector.parse("Testo 1.0.0"))
11+
}
12+
13+
fun testParse_versionWithPreRelease() {
14+
assertEquals("2.3.1-beta.1", TestoVersionDetector.parse("Testo 2.3.1-beta.1"))
15+
}
16+
17+
fun testParse_emptyAfterPrefix() {
18+
try {
19+
TestoVersionDetector.parse("Testo ")
20+
fail("Expected ExecutionException")
21+
} catch (_: ExecutionException) {
22+
// expected
23+
}
24+
}
25+
26+
fun testParse_noPrefix() {
27+
// "substringAfter" returns original string if delimiter not found
28+
assertEquals("SomeOtherOutput", TestoVersionDetector.parse("SomeOtherOutput"))
29+
}
30+
31+
fun testGetVersionOptions() {
32+
val options = TestoVersionDetector.getVersionOptions()
33+
assertEquals(2, options.size)
34+
assertEquals("--version", options[0])
35+
assertEquals("--no-ansi", options[1])
36+
}
37+
}

0 commit comments

Comments
 (0)