Skip to content

Commit 79a4a1b

Browse files
authored
Implement TestProjectOption (#22)
1 parent 06d6477 commit 79a4a1b

File tree

7 files changed

+183
-154
lines changed

7 files changed

+183
-154
lines changed

src/main/kotlin/com/featurevisor/sdk/Instance.kt

+5-8
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,9 @@
33
*/
44
package com.featurevisor.sdk
55

6-
import com.featurevisor.sdk.FeaturevisorError.FetchingDataFileFailed
76
import com.featurevisor.sdk.FeaturevisorError.MissingDatafileOptions
8-
import com.featurevisor.types.BucketKey
9-
import com.featurevisor.types.BucketValue
10-
import com.featurevisor.types.Context
11-
import com.featurevisor.types.DatafileContent
12-
import com.featurevisor.types.EventName
7+
import com.featurevisor.types.*
138
import com.featurevisor.types.EventName.*
14-
import com.featurevisor.types.Feature
15-
import com.featurevisor.types.StickyFeatures
169
import kotlinx.coroutines.Job
1710
import kotlinx.serialization.decodeFromString
1811
import kotlinx.serialization.json.Json
@@ -116,6 +109,10 @@ class FeaturevisorInstance private constructor(options: InstanceOptions) {
116109
}
117110
}
118111

112+
fun setLogLevels(levels: List<Logger.LogLevel>) {
113+
this.logger?.setLevels(levels)
114+
}
115+
119116
fun setDatafile(datafileJSON: String) {
120117
val data = datafileJSON.toByteArray(Charsets.UTF_8)
121118
try {

src/main/kotlin/com/featurevisor/testRunner/CommandExecuter.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,26 @@ import java.util.concurrent.TimeUnit
66

77
internal fun getJsonForFeatureUsingCommand(featureName: String, environment: String, projectRootPath: String) =
88
try {
9-
createCommand(featureName, environment).runCommand(getFileForSpecificPath(projectRootPath))
9+
createCommandForSpecificFeature(featureName, environment).runCommand(getFileForSpecificPath(projectRootPath))
1010
} catch (e: Exception) {
1111
printMessageInRedColor("Exception in Commandline execution --> ${e.message}")
1212
null
1313
}
1414

15-
private fun createCommand(featureName: String, environment: String) =
15+
fun getJsonForDataFile(environment: String, projectRootPath: String) =
16+
try {
17+
createCommandAccordingToEnvironment(environment).runCommand(getFileForSpecificPath(projectRootPath))
18+
} catch (e: Exception) {
19+
printMessageInRedColor("Exception in Commandline execution --> ${e.message}")
20+
null
21+
}
22+
23+
private fun createCommandForSpecificFeature(featureName: String, environment: String) =
1624
"npx featurevisor build --feature=$featureName --environment=$environment --print --pretty"
1725

26+
private fun createCommandAccordingToEnvironment(environment: String) =
27+
"npx featurevisor build --environment=$environment --print --pretty"
28+
1829
private fun String.runCommand(workingDir: File): String? =
1930
try {
2031
val parts = this.split("\\s".toRegex())

src/main/kotlin/com/featurevisor/testRunner/TestExecuter.kt

+62-102
Original file line numberDiff line numberDiff line change
@@ -1,144 +1,89 @@
1-
//@file:JvmName("TestExecuter")
21
package com.featurevisor.testRunner
32

43
import com.featurevisor.types.*
54
import java.io.File
65

7-
fun main(args: Array<String>) {
8-
when (args.size) {
9-
0 -> {
10-
startTest()
11-
}
12-
13-
1 -> {
14-
val rootPathInParam = args[0]
15-
startTest(rootPathInParam)
16-
}
17-
18-
else -> {
19-
val rootPathInParam = args[0]
20-
val testDirInParam = args[1]
21-
startTest(rootPathInParam, testDirInParam)
22-
}
23-
}
24-
}
25-
26-
fun startTest(projectRootPath: String = "", testDirPath: String = "") {
27-
val rootPath = projectRootPath.ifEmpty {
28-
getRootProjectDir()
29-
}
30-
val testDir = testDirPath.ifEmpty {
31-
"tests"
32-
}
33-
getAllFilesInDirectory(rootPath, testDir)
34-
}
35-
36-
internal fun getAllFilesInDirectory(projectRootPath: String, testDirPath: String) {
37-
val folder = File("$projectRootPath/$testDirPath")
6+
data class TestProjectOption(
7+
val keyPattern: String = "",
8+
val assertionPattern: String = "",
9+
val verbose: Boolean = false,
10+
val showDatafile: Boolean = false,
11+
val onlyFailures: Boolean = false,
12+
val fast: Boolean = false,
13+
val testDirPath: String = "tests",
14+
val projectRootPath: String = getRootProjectDir()
15+
)
16+
17+
fun startTest(option: TestProjectOption) {
18+
var hasError = false
19+
val folder = File("${option.projectRootPath}/${option.testDirPath}")
3820
val listOfFiles = folder.listFiles()
3921
var executionResult: ExecutionResult? = null
40-
22+
val startTime = System.currentTimeMillis()
4123
var passedTestsCount = 0
4224
var failedTestsCount = 0
43-
4425
var passedAssertionsCount = 0
4526
var failedAssertionsCount = 0
4627

4728
if (!listOfFiles.isNullOrEmpty()) {
29+
val datafile =
30+
if (option.fast) buildDataFileForBothEnvironments(projectRootPath = option.projectRootPath) else DataFile(
31+
null,
32+
null
33+
)
34+
if (option.fast && (datafile.stagingDataFiles == null || datafile.productionDataFiles == null)) {
35+
return
36+
}
4837
for (file in listOfFiles) {
4938
if (file.isFile) {
5039
if (file.extension.equals("yml", true)) {
5140
val filePath = file.absoluteFile.path
5241
try {
53-
executionResult = testAssertion(filePath, projectRootPath)
42+
executionResult = executeTest(filePath, dataFile = datafile, option)
5443
} catch (e: Exception) {
5544
printMessageInRedColor("Exception in $filePath --> ${e.message}")
5645
}
5746

47+
if (executionResult == null) {
48+
return
49+
}
5850

59-
if (executionResult?.passed == true) {
51+
if (executionResult.passed) {
6052
passedTestsCount++
6153
} else {
54+
hasError = true
6255
failedTestsCount++
6356
}
6457

65-
passedAssertionsCount += executionResult?.assertionsCount?.passed ?: 0
66-
failedAssertionsCount += executionResult?.assertionsCount?.failed ?: 0
67-
58+
passedAssertionsCount += executionResult.assertionsCount.passed
59+
failedAssertionsCount += executionResult.assertionsCount.failed
6860
} else {
6961
printMessageInRedColor("The file is not valid yml file")
7062
}
7163
}
7264
}
73-
printMessageInGreenColor("Test specs: $passedTestsCount passed, $failedTestsCount failed")
74-
printMessageInGreenColor("Test Assertion: $passedAssertionsCount passed, $failedAssertionsCount failed")
75-
} else {
76-
printMessageInRedColor("Directory is Empty or not exists")
77-
}
78-
}
79-
80-
fun testSingleFeature(featureKey: String, projectRootPath: String = "", testDirPath: String = "") {
81-
val rootPath = projectRootPath.ifEmpty { getRootProjectDir() }
82-
val testDir = testDirPath.ifEmpty { "tests" }
8365

84-
val test = parseTestFeatureAssertions("$rootPath/$testDir/$featureKey.feature.yml")
85-
86-
test?.let {
87-
val executionResult = ExecutionResult(
88-
passed = false,
89-
assertionsCount = AssertionsCount(0, 0)
90-
)
66+
val endTime = System.currentTimeMillis() - startTime
9167

92-
val testResult = testFeature(testFeature = (test as Test.Feature).value, projectRootPath)
93-
94-
printTestResult(testResult)
95-
96-
if (!testResult.passed) {
97-
executionResult.passed = false
98-
99-
executionResult.assertionsCount.failed = testResult.assertions.count { !it.passed }
100-
executionResult.assertionsCount.passed += testResult.assertions.size - executionResult.assertionsCount.failed
101-
} else {
102-
executionResult.assertionsCount.passed = testResult.assertions.size
68+
if (!option.onlyFailures || hasError) {
69+
printNormalMessage("\n----")
10370
}
71+
printNormalMessage("")
10472

105-
printMessageInGreenColor("Test Assertion: ${executionResult.assertionsCount.passed} passed, ${executionResult.assertionsCount.failed} failed")
106-
}
107-
108-
}
109-
110-
fun testSingleSegment(segmentKey: String, projectRootPath: String = "", testDirPath: String = "") {
111-
112-
val rootPath = projectRootPath.ifEmpty { getRootProjectDir() }
113-
val testDir = testDirPath.ifEmpty { "tests" }
114-
115-
val test = parseTestFeatureAssertions("$rootPath/$testDir/$segmentKey.segment.yml")
116-
117-
test?.let {
118-
val executionResult = ExecutionResult(
119-
passed = false,
120-
assertionsCount = AssertionsCount(0, 0)
121-
)
122-
123-
val testResult = testSegment(test = (test as Test.Segment).value, projectRootPath)
124-
125-
printTestResult(testResult)
126-
127-
if (!testResult.passed) {
128-
executionResult.passed = false
129-
130-
executionResult.assertionsCount.failed = testResult.assertions.count { !it.passed }
131-
executionResult.assertionsCount.passed += testResult.assertions.size - executionResult.assertionsCount.failed
73+
if (hasError) {
74+
printMessageInRedColor("\n\nTest specs: $passedTestsCount passed, $failedTestsCount failed")
75+
printMessageInRedColor("Test Assertion: $passedAssertionsCount passed, $failedAssertionsCount failed")
13276
} else {
133-
executionResult.assertionsCount.passed = testResult.assertions.size
77+
printMessageInGreenColor("\n\nTest specs: $passedTestsCount passed, $failedTestsCount failed")
78+
printMessageInGreenColor("Test Assertion: $passedAssertionsCount passed, $failedAssertionsCount failed")
13479
}
135-
136-
printMessageInGreenColor("Test Assertion: ${executionResult.assertionsCount.passed} passed, ${executionResult.assertionsCount.failed} failed")
137-
80+
printBoldMessage("Time: ${prettyDuration(endTime)}")
81+
} else {
82+
printMessageInRedColor("Directory is Empty or not exists")
13883
}
13984
}
14085

141-
private fun testAssertion(filePath: String, projectRootPath: String): ExecutionResult {
86+
private fun executeTest(filePath: String, dataFile: DataFile, option: TestProjectOption): ExecutionResult {
14287
val test = parseTestFeatureAssertions(filePath)
14388

14489
val executionResult = ExecutionResult(
@@ -147,17 +92,32 @@ private fun testAssertion(filePath: String, projectRootPath: String): ExecutionR
14792
)
14893

14994
test?.let {
95+
val key = when (test) {
96+
is Test.Feature -> test.value.key
97+
is Test.Segment -> test.value.key
98+
}
99+
100+
if (option.keyPattern.isNotEmpty() && !key.contains(option.keyPattern)) {
101+
return@let
102+
}
103+
150104
val testResult: TestResult = when (test) {
151105
is Test.Feature -> {
152-
testFeature(test.value, projectRootPath)
106+
testFeature(test.value, dataFile = dataFile, option)
153107
}
154108

155109
is Test.Segment -> {
156-
testSegment(test.value, projectRootPath)
110+
testSegment(test.value, option.projectRootPath)
157111
}
158112
}
159113

160-
printTestResult(testResult)
114+
if (!option.onlyFailures) {
115+
printTestResult(testResult)
116+
} else {
117+
if (!testResult.passed) {
118+
printTestResult(testResult)
119+
}
120+
}
161121

162122
if (!testResult.passed) {
163123
executionResult.passed = false

0 commit comments

Comments
 (0)