From e90def4181a51b9c4aaba54b2ebdd994d29fdf01 Mon Sep 17 00:00:00 2001 From: Rd Date: Tue, 4 Jun 2024 12:53:26 +0530 Subject: [PATCH 01/12] Introduce RunCoverageForTestTarget script --- scripts/BUILD.bazel | 9 +++++++++ .../org/oppia/android/scripts/coverage/BUILD.bazel | 14 ++++++++++++++ .../scripts/coverage/RunCoverageForTestTarget.kt | 5 +++++ 3 files changed, 28 insertions(+) create mode 100644 scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel create mode 100644 scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt diff --git a/scripts/BUILD.bazel b/scripts/BUILD.bazel index 689cf6e53d2..23587533fa0 100644 --- a/scripts/BUILD.bazel +++ b/scripts/BUILD.bazel @@ -237,6 +237,15 @@ kt_jvm_binary( ], ) +kt_jvm_binary( + name = "run_coverage_for_test_target", + testonly = True, + main_class = "org.oppia.android.scripts.coverage.RunCoverageForTestTargetKt", + runtime_deps = [ + "//scripts/src/java/org/oppia/android/scripts/coverage:run_coverage_for_test_target_lib", + ], +) + # Note that this is intentionally not test-only since it's used by the app build pipeline. Also, # this apparently needs to be a java_binary to set up runfiles correctly when executed within a # Starlark rule as a tool. diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel new file mode 100644 index 00000000000..3b0c0f9d886 --- /dev/null +++ b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel @@ -0,0 +1,14 @@ +load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library") + +kt_jvm_library( + name = "run_coverage_for_test_target_lib", + testonly = True, + srcs = [ + "RunCoverageForTestTarget.kt", + ], + visibility = ["//scripts:oppia_script_binary_visibility"], + deps = [ + "//scripts/src/java/org/oppia/android/scripts/common:bazel_client", + "//scripts/src/java/org/oppia/android/scripts/common:git_client", + ], +) \ No newline at end of file diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt new file mode 100644 index 00000000000..f5850688ab7 --- /dev/null +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -0,0 +1,5 @@ +package org.oppia.android.scripts.coverage + +fun main(vararg args: String) { + println("Running coverage for test target: ${args[0]}") +} \ No newline at end of file From 43f5f61305024c2bc99278bca02fa60ee805a02d Mon Sep 17 00:00:00 2001 From: Rd Date: Tue, 4 Jun 2024 14:11:09 +0530 Subject: [PATCH 02/12] Fix lint new line and kdoc checks --- .../java/org/oppia/android/scripts/coverage/BUILD.bazel | 2 +- .../android/scripts/coverage/RunCoverageForTestTarget.kt | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel index 3b0c0f9d886..88cebeac1d7 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel +++ b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel @@ -11,4 +11,4 @@ kt_jvm_library( "//scripts/src/java/org/oppia/android/scripts/common:bazel_client", "//scripts/src/java/org/oppia/android/scripts/common:git_client", ], -) \ No newline at end of file +) diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt index f5850688ab7..99544e09c7d 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -1,5 +1,10 @@ package org.oppia.android.scripts.coverage +/** + * Entry point function for running coverage analysis for a single test target. + * + * @param args Command-line arguments. + */ fun main(vararg args: String) { println("Running coverage for test target: ${args[0]}") -} \ No newline at end of file +} From 6915d64d3cecda1f7ee123abda6c0b4842253d5d Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 5 Jun 2024 13:34:54 +0530 Subject: [PATCH 03/12] Execute Bazel Command to run coverage on the test target --- .../android/scripts/common/BazelClient.kt | 13 ++++ .../android/scripts/coverage/BUILD.bazel | 14 ++++ .../scripts/coverage/CoverageRunner.kt | 71 +++++++++++++++++++ .../coverage/RunCoverageForTestTarget.kt | 41 ++++++++++- 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt diff --git a/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt b/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt index 9aede2fd16f..706adbba03c 100644 --- a/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt +++ b/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt @@ -130,6 +130,19 @@ class BazelClient(private val rootDirectory: File, private val commandExecutor: return correctedTargets } + /** + * Runs code coverage for the specified Bazel test target. + * + * @param bazelTestTarget Bazel test target for which code coverage will be run. + * @return generated coverageResult output + */ + fun runCoverageForTestTarget(bazelTestTarget: String): List { + return executeBazelCommand( + "coverage", + bazelTestTarget + ) + } + /** * Returns the results of a query command with a potentially large list of [values] that will be * split up into multiple commands to avoid overflow the system's maximum argument limit. diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel index 88cebeac1d7..924011c5225 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel +++ b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel @@ -7,6 +7,20 @@ kt_jvm_library( "RunCoverageForTestTarget.kt", ], visibility = ["//scripts:oppia_script_binary_visibility"], + deps = [ + "//scripts/src/java/org/oppia/android/scripts/coverage:coverage_runner", + "//scripts/src/java/org/oppia/android/scripts/common:bazel_client", + "//scripts/src/java/org/oppia/android/scripts/common:git_client", + ], +) + +kt_jvm_library( + name = "coverage_runner", + testonly = True, + srcs = [ + "CoverageRunner.kt", + ], + visibility = ["//scripts:oppia_script_binary_visibility"], deps = [ "//scripts/src/java/org/oppia/android/scripts/common:bazel_client", "//scripts/src/java/org/oppia/android/scripts/common:git_client", diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt new file mode 100644 index 00000000000..6ed50cb9c93 --- /dev/null +++ b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt @@ -0,0 +1,71 @@ +package org.oppia.android.scripts.coverage + +import org.oppia.android.scripts.common.BazelClient +import org.oppia.android.scripts.common.CommandExecutor +import org.oppia.android.scripts.common.CommandExecutorImpl +import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.async +import kotlinx.coroutines.Deferred +import java.io.File + +class CoverageRunner { + fun runWithCoverageAsync( + repoRoot: File, + scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher, + bazelTestTarget: String + ): Deferred { + return CoroutineScope(scriptBgDispatcher).async { + val coverageData = getCoverage(repoRoot, scriptBgDispatcher, bazelTestTarget) + val data = coverageData.await() + parseData(data) + } + } + + fun getCoverage( + repoRoot: File, + scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher, + bazelTestTarget: String + ): Deferred> { + return CoroutineScope(scriptBgDispatcher).async { + val commandExecutor: CommandExecutor = CommandExecutorImpl(scriptBgDispatcher) + val bazelClient = BazelClient(repoRoot, commandExecutor) + val coverageData = bazelClient.runCoverageForTestTarget(bazelTestTarget) + coverageData + } + } + + fun parseData(data: List) { + // Implementation to parse the coverage data file path String + println("Parsed Data: $data") + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt index 99544e09c7d..c8e18813b43 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -1,10 +1,49 @@ package org.oppia.android.scripts.coverage +import org.oppia.android.scripts.coverage.CoverageRunner +import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher +import kotlinx.coroutines.runBlocking +import java.io.File + /** * Entry point function for running coverage analysis for a single test target. * * @param args Command-line arguments. */ fun main(vararg args: String) { - println("Running coverage for test target: ${args[0]}") + val repoRoot = File(args[0]).absoluteFile.normalize() + val targetPath = args[1] + + RunCoverageForTestTarget().runCoverage(repoRoot, targetPath) +} + +/** + * Class responsible for analyzing target files for coverage and generating reports. + */ +class RunCoverageForTestTarget() { + + /** + * Analyzes target file for coverage, generates chosen reports accordingly. + * + * @param targetFile Path to the file to analyze. + * @param outputFormats Output formats for the coverage reports. + * @throws IllegalStateException if computed coverage is below min required. + */ + fun runCoverage(repoRoot: File, targetPath: String) { + runWithCoverageAnalysis(repoRoot, targetPath) + } + + /** + * Runs coverage analysis on the specified target file asynchronously. + * + * @param targetFile Path to the target file to analyze coverage. + * @return A deferred result representing the coverage report. + */ + fun runWithCoverageAnalysis(repoRoot: File, targetPath: String) { + ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher -> + runBlocking { + CoverageRunner().runWithCoverageAsync(repoRoot, scriptBgDispatcher, targetPath).await() + } + } + } } From 9cb729bc1f45214393afa3fac9ff55fb7c216ae8 Mon Sep 17 00:00:00 2001 From: Rd Date: Wed, 5 Jun 2024 15:59:47 +0530 Subject: [PATCH 04/12] Parse the coverage execution result to acquire the generated coverage data file path --- .../scripts/coverage/CoverageRunner.kt | 75 ++++++++++--------- .../coverage/RunCoverageForTestTarget.kt | 6 +- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt index 6ed50cb9c93..ffd286b160c 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt @@ -9,19 +9,39 @@ import kotlinx.coroutines.async import kotlinx.coroutines.Deferred import java.io.File +/** + * Class responsible for running coverage analysis asynchronously. + */ class CoverageRunner { - fun runWithCoverageAsync( + + /** + * Runs coverage analysis asynchronously for the Bazel test target. + * + * @param repoRoot the absolute path to the working root directory + * @param scriptBgDispatcher the [ScriptBackgroundCoroutineDispatcher] to be used for running the coverage command + * @param bazelTestTarget Bazel test target to analyze coverage. + * @return a deferred value that contains the path of the coverage data file [will contain the proto for the coverage data]. + */ + suspend fun runWithCoverageAsync( repoRoot: File, scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher, bazelTestTarget: String - ): Deferred { + ): Deferred { return CoroutineScope(scriptBgDispatcher).async { val coverageData = getCoverage(repoRoot, scriptBgDispatcher, bazelTestTarget) val data = coverageData.await() - parseData(data) + parseCoverageDataFile(data) } } + /** + * Runs coverage command for the Bazel test target. + * + * @param repoRoot the absolute path to the working root directory + * @param scriptBgDispatcher the [ScriptBackgroundCoroutineDispatcher] to be used for running the coverage command + * @param bazelTestTarget Bazel test target to analyze coverage. + * @return a deferred value that contains the result of the coverage execution. + */ fun getCoverage( repoRoot: File, scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher, @@ -35,37 +55,22 @@ class CoverageRunner { } } - fun parseData(data: List) { - // Implementation to parse the coverage data file path String - println("Parsed Data: $data") + /** + * Parse the coverage command result to extract the path of the coverage data file. + * + * @param data the result from the execution of the coverage command + * @return the extracted path of the coverage data file. + */ + fun parseCoverageDataFile(data: List) : String? { + val regex = ".*coverage\\.dat$".toRegex() + for (line in data) { + val match = regex.find(line) + val extractedPath = match?.value?.substringAfterLast(",")?.trim() + if (extractedPath != null) { + println("Parsed Coverage Data File: $extractedPath") + return extractedPath + } + } + return null } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt index c8e18813b43..f57d798c4d1 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -25,9 +25,8 @@ class RunCoverageForTestTarget() { /** * Analyzes target file for coverage, generates chosen reports accordingly. * + * @param repoRoot the absolute path to the working root directory * @param targetFile Path to the file to analyze. - * @param outputFormats Output formats for the coverage reports. - * @throws IllegalStateException if computed coverage is below min required. */ fun runCoverage(repoRoot: File, targetPath: String) { runWithCoverageAnalysis(repoRoot, targetPath) @@ -36,8 +35,9 @@ class RunCoverageForTestTarget() { /** * Runs coverage analysis on the specified target file asynchronously. * + * @param repoRoot the absolute path to the working root directory * @param targetFile Path to the target file to analyze coverage. - * @return A deferred result representing the coverage report. + * @return [A deferred result representing the coverage report]. */ fun runWithCoverageAnalysis(repoRoot: File, targetPath: String) { ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher -> From 7bc324b93644997054a41fd77ea475bfb63f5887 Mon Sep 17 00:00:00 2001 From: Rd Date: Fri, 7 Jun 2024 13:53:25 +0530 Subject: [PATCH 05/12] Implemented functionality to TestBazelWorkspace utility to add source file content and its related test content in the provided subpackage --- .../scripts/testing/TestBazelWorkspace.kt | 118 ++++++++++++++++++ .../android/scripts/common/BazelClientTest.kt | 44 +++++++ 2 files changed, 162 insertions(+) diff --git a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt index 7c57cf0d10c..0c7fb58ed20 100644 --- a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt +++ b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt @@ -50,6 +50,124 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { assertThat(bazelRcFile.exists()).isTrue() } + /** + * Adds a source file with the specified name and content to the specified subpackage, + * and updates the corresponding build configuration. + * + * @param filename the name of the source file (without the .kt extension) + * @param sourceContent the content of the source file + * @param subpackage the subpackage under which the source file should be added + * @return the target name of the added source file + */ + fun addSourceContentAndBuildFile( + filename: String, + sourceContent: String, + sourceSubpackage: String + ): String { + initEmptyWorkspace() // Ensure the workspace is at least initialized. + + // Create the source subpackage directory if it doesn't exist + if (!File(temporaryRootFolder.root, sourceSubpackage.replace(".", "/")).exists()) { + temporaryRootFolder.newFolder(*(sourceSubpackage.split(".")).toTypedArray()) + } + + // Create the source file + val sourceFile = temporaryRootFolder.newFile("${sourceSubpackage.replace(".", "/")}/$filename.kt") + sourceFile.writeText(sourceContent) + + // Create or update the BUILD file for the source file + val buildFileRelativePath = "${sourceSubpackage.replace(".", "/")}/BUILD.bazel" + val buildFile = File(temporaryRootFolder.root, buildFileRelativePath) + if (!buildFile.exists()) { + temporaryRootFolder.newFile(buildFileRelativePath) + } + + prepareBuildFileForLibraries(buildFile) + + val libTargetName = "${sourceSubpackage}:${filename}_lib" + buildFile.appendText( + """" + kt_jvm_library( + name = "${filename}_lib", + srcs=["$filename}.kt"], + ) + """.trimIndent() + "\n" + ) + return libTargetName + } + + /** + * Adds a test file with the specified name and content to the specified subpackage, + * and updates the corresponding build configuration. + * + * @param testName the name of the test file (without the .kt extension) + * @param testContent the content of the test file + * @param libTargetName the target name of the library the test depends on + * @param testSubpackage the subpackage for the test file + */ + fun addTestContentAndBuildFile( + testName: String, + testContent: String, + libTargetName: String, + testSubpackage: String + ) { + initEmptyWorkspace() // Ensure the workspace is at least initialized. + + // Create the test subpackage directory for the test file if it doesn't exist + if (!File(temporaryRootFolder.root, testSubpackage.replace(".", "/")).exists()) { + temporaryRootFolder.newFolder(*(testSubpackage.split(".")).toTypedArray()) + } + + // Create the test file + val testFile = temporaryRootFolder.newFile("${testSubpackage.replace(".", "/")}/$testName.kt") + testFile.writeText(testContent) + + // Create or update the BUILD file for the test file + val testBuildFileRelativePath = "${testSubpackage.replace(".", "/")}/BUILD.bazel" + val testBuildFile = File(temporaryRootFolder.root, testBuildFileRelativePath) + if (!testBuildFile.exists()) { + temporaryRootFolder.newFile(testBuildFileRelativePath) + } + prepareBuildFileForTests(testBuildFile) + + // Add the test file to the BUILD file with appropriate dependencies + testBuildFile.appendText( + """ + kt_jvm_test( + name = "$testName", + srcs = ["${testName}.kt"], + deps = [ + "//third_party:org_jetbrains_kotlin_kotlin-test-junit", + "$libTargetName", + ], + ) + """.trimIndent() + "\n" + ) + } + + /** + * Adds a file with the specified name and content, along with its corresponding test file and + * test content, to the specified subpackage. Ensures the appropriate build configurations are created. + * + * @param filename the name of the source file (without the .kt extension) + * @param sourceContent the content of the source file + * @param testContent the content of the test file + * @param subpackage the subpackage for the source and test files + */ + fun addSourceFileAndItsTestFileWithContent( + filename: String, + sourceContent: String, + testContent: String, + subpackage: String, + ) { + val sourceSubpackage = "$subpackage/source" + val libTargetName = addSourceContentAndBuildFile(filename, sourceContent, sourceSubpackage) + + val testSubpackage = "$subpackage/test" + val testFileName = "${filename}Test" + addTestContentAndBuildFile(testFileName, testContent, libTargetName, testSubpackage) + } + /** * Generates and adds a new kt_jvm_test target with the target name [testName] and test file * [testFile]. This can be used to add multiple tests to the same build file, and will diff --git a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt index 3f451d354b8..3c764939468 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt @@ -379,6 +379,50 @@ class BazelClientTest { assertThat(thirdPartyDependenciesList).doesNotContain("@maven//:androidx_annotation_annotation") } + @Test + fun testRunCodeCoverageForATestTarget() { +// val bazelClient = BazelClient(tempFolder.root, commandExecutor) + testBazelWorkspace.initEmptyWorkspace() + testBazelWorkspace.createTest("FirstTest") + + + // Verify the test file is created + val testFile = File(tempFolder.root, "FirstTest.kt") + assertThat(testFile.exists()).isTrue() + assertThat(testFile.isFile).isTrue() + + val addsource = testBazelWorkspace.addSourceFileAndItsTestFileWithContent("test1", "Hi", "@Test", "cc") + println("Add Source result: $addsource") + + listFilesInDirectory(tempFolder.root) +// bazelClient.runCoverageForTestTarget("//utility/src/test/java/org/oppia/android/util/parser/math:MathModelTest") + + // Verify the WORKSPACE file exists + val workspaceFile = File(tempFolder.root, "WORKSPACE") + assertThat(workspaceFile.exists()).isTrue() + assertThat(workspaceFile.isFile).isTrue() + + // Print the contents of the WORKSPACE file + println("\nContents of WORKSPACE file:") + println(workspaceFile.readText()) + + // Verify the BUILD.bazel file exists + val bazelFile = File(tempFolder.root, "BUILD.bazel") + assertThat(bazelFile.exists()).isTrue() + assertThat(bazelFile.isFile).isTrue() + + // Print the contents of the BUILD.bazel file + println("Contents of BUILD BAZEL file:") + println(bazelFile.readText()) + + } + + private fun listFilesInDirectory(directory: File) { + directory.walk().forEach { + println(it.relativeTo(directory)) + } + } + private fun fakeCommandExecutorWithResult(singleLine: String) { // Fake a Bazel command's results to return jumbled results. This has been observed to happen // sometimes in CI, but doesn't have a known cause. The utility is meant to de-jumble these in From 95729a3727214e7442c488615a554b507c62844c Mon Sep 17 00:00:00 2001 From: Rd Date: Sun, 9 Jun 2024 14:09:53 +0530 Subject: [PATCH 06/12] Sample Test data and Listing all contents --- .../android/scripts/common/BazelClient.kt | 37 ++++- .../scripts/common/CommandExecutorImpl.kt | 2 +- .../scripts/testing/TestBazelWorkspace.kt | 134 ++++++++++++++++- .../android/scripts/common/BazelClientTest.kt | 139 ++++++++++++++++-- 4 files changed, 295 insertions(+), 17 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt b/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt index 706adbba03c..cf198c10963 100644 --- a/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt +++ b/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt @@ -136,11 +136,44 @@ class BazelClient(private val rootDirectory: File, private val commandExecutor: * @param bazelTestTarget Bazel test target for which code coverage will be run. * @return generated coverageResult output */ - fun runCoverageForTestTarget(bazelTestTarget: String): List { - return executeBazelCommand( +// fun runCoverageForTestTarget(bazelTestTarget: String): List { + fun runCoverageForTestTarget(bazelTestTarget: String): String? { + /*return executeBazelCommand( + "coverage", + bazelTestTarget + )*/ + val result = executeBazelCommand( "coverage", bazelTestTarget ) + + println("Coverage data from exe: $result") + val filedata = parseCoverageDataFile(result) + + println("Coverage data path from exe: $filedata") + val file = File(filedata) + + if (file.exists() && file.isFile) { + val contents = file.readText() + println(contents) + } else { + println("File does not exist or is not a valid file: $filedata") + } + + return filedata + } + + fun parseCoverageDataFile(data: List) : String? { + val regex = ".*coverage\\.dat$".toRegex() + for (line in data) { + val match = regex.find(line) + val extractedPath = match?.value?.substringAfterLast(",")?.trim() + if (extractedPath != null) { + println("Parsed Coverage Data File: $extractedPath") + return extractedPath + } + } + return null } /** diff --git a/scripts/src/java/org/oppia/android/scripts/common/CommandExecutorImpl.kt b/scripts/src/java/org/oppia/android/scripts/common/CommandExecutorImpl.kt index 01476cbf3cd..05a90b02110 100644 --- a/scripts/src/java/org/oppia/android/scripts/common/CommandExecutorImpl.kt +++ b/scripts/src/java/org/oppia/android/scripts/common/CommandExecutorImpl.kt @@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit * The default amount of time that should be waited before considering a process as 'hung', in * milliseconds. */ -const val WAIT_PROCESS_TIMEOUT_MS = 60_000L +const val WAIT_PROCESS_TIMEOUT_MS = 600_000L /** Default implementation of [CommandExecutor]. */ class CommandExecutorImpl( diff --git a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt index 0c7fb58ed20..b489f708b8f 100644 --- a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt +++ b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt @@ -50,6 +50,97 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { assertThat(bazelRcFile.exists()).isTrue() } + fun addSampleSourceAndTestFile( + filename: String, + sourceContent: String, + testContent: String, + subpackage: String + ) { + val sourceSubpackage = "$subpackage/main/java/com/example" + addSampleSourceContentAndBuildFile(filename, sourceContent, sourceSubpackage) + + val testSubpackage = "$subpackage/test/java/com/example" + val testFileName = "Test${filename}" + addSampleTestContentAndBuildFile(testFileName, testContent, testSubpackage) + } + + fun addSampleSourceContentAndBuildFile( + filename: String, + sourceContent: String, + sourceSubpackage: String + ) { + initEmptyWorkspace() + + // Create the source subpackage directory if it doesn't exist + if (!File(temporaryRootFolder.root, sourceSubpackage.replace(".", "/")).exists()) { + temporaryRootFolder.newFolder(*(sourceSubpackage.split(".")).toTypedArray()) + } + + // Create the source file + val sourceFile = temporaryRootFolder.newFile("${sourceSubpackage.replace(".", "/")}/$filename.java") + sourceFile.writeText(sourceContent) + + // Create or update the BUILD file for the source file + val buildFileRelativePath = "${sourceSubpackage.replace(".", "/")}/BUILD.bazel" + val buildFile = File(temporaryRootFolder.root, buildFileRelativePath) + if (!buildFile.exists()) { + temporaryRootFolder.newFile(buildFileRelativePath) + } + + //prepareBuildFileForLibraries(buildFile) + + //val libTargetName = "//${sourceSubpackage}:${filename}_lib" + buildFile.appendText( + """ + package( + default_visibility = ["//visibility:public"], + ) + + java_library( + name = "collatz_lib", + srcs=["Collatz.java"], + ) + """.trimIndent() + "\n" + ) + } + + fun addSampleTestContentAndBuildFile( + testName: String, + testContent: String, + testSubpackage: String + ) { + initEmptyWorkspace() + + // Create the test subpackage directory for the test file if it doesn't exist + if (!File(temporaryRootFolder.root, testSubpackage.replace(".", "/")).exists()) { + temporaryRootFolder.newFolder(*(testSubpackage.split(".")).toTypedArray()) + } + + // Create the test file + val testFile = temporaryRootFolder.newFile("${testSubpackage.replace(".", "/")}/$testName.java") + testFile.writeText(testContent) + + // Create or update the BUILD file for the test file + val testBuildFileRelativePath = "${testSubpackage.replace(".", "/")}/BUILD.bazel" + val testBuildFile = File(temporaryRootFolder.root, testBuildFileRelativePath) + if (!testBuildFile.exists()) { + temporaryRootFolder.newFile(testBuildFileRelativePath) + } + //prepareBuildFileForTests(testBuildFile) + + // Add the test file to the BUILD file with appropriate dependencies + testBuildFile.appendText( + """ + java_test( + name = "test", + srcs = ["TestCollatz.java"], + test_class = "com.example.TestCollatz", + deps = ["//coverage/main/java/com/example:collatz_lib"], + ) + """.trimIndent() + "\n" + ) + } + /** * Adds a source file with the specified name and content to the specified subpackage, * and updates the corresponding build configuration. @@ -65,6 +156,7 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { sourceSubpackage: String ): String { initEmptyWorkspace() // Ensure the workspace is at least initialized. + ensureWorkspaceIsConfiguredForKotlin() // Create the source subpackage directory if it doesn't exist if (!File(temporaryRootFolder.root, sourceSubpackage.replace(".", "/")).exists()) { @@ -84,9 +176,9 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { prepareBuildFileForLibraries(buildFile) - val libTargetName = "${sourceSubpackage}:${filename}_lib" + val libTargetName = "//${sourceSubpackage}:${filename}_lib" buildFile.appendText( - """" + """ kt_jvm_library( name = "${filename}_lib", srcs=["$filename}.kt"], @@ -112,6 +204,7 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { testSubpackage: String ) { initEmptyWorkspace() // Ensure the workspace is at least initialized. + ensureWorkspaceIsConfiguredForKotlin() // Create the test subpackage directory for the test file if it doesn't exist if (!File(temporaryRootFolder.root, testSubpackage.replace(".", "/")).exists()) { @@ -137,7 +230,7 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { name = "$testName", srcs = ["${testName}.kt"], deps = [ - "//third_party:org_jetbrains_kotlin_kotlin-test-junit", + "@maven//:junit_junit", "$libTargetName", ], ) @@ -145,6 +238,39 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { ) } + fun setupGeneralCoverageBuildFile( + sourceLibTargetName: String, + testTargetName: String, + coverageSubpackage: String + ) { + initEmptyWorkspace() // Ensure the workspace is at least initialized. + ensureWorkspaceIsConfiguredForKotlin() // Ensure Kotlin rules are set up. + + // Create the coverage subpackage directory if it doesn't exist + if (!File(temporaryRootFolder.root, coverageSubpackage.replace(".", "/")).exists()) { + temporaryRootFolder.newFolder(*(coverageSubpackage.split(".")).toTypedArray()) + } + + // Create or update the BUILD file for the coverage package + val coverageBuildFileRelativePath = "${coverageSubpackage.replace(".", "/")}/BUILD.bazel" + val coverageBuildFile = File(temporaryRootFolder.root, coverageBuildFileRelativePath) + if (!coverageBuildFile.exists()) { + temporaryRootFolder.newFile(coverageBuildFileRelativePath) + } + + coverageBuildFile.appendText( + """ + kt_jvm_binary( + name = "coverage_runner", + srcs = ["//${coverageSubpackage.replace(".", "/")}:$testTargetName"], + deps = [ + "$sourceLibTargetName", + ], + ) + """.trimIndent() + "\n" + ) + } + /** * Adds a file with the specified name and content, along with its corresponding test file and * test content, to the specified subpackage. Ensures the appropriate build configurations are created. @@ -166,6 +292,8 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { val testSubpackage = "$subpackage/test" val testFileName = "${filename}Test" addTestContentAndBuildFile(testFileName, testContent, libTargetName, testSubpackage) + + setupGeneralCoverageBuildFile(libTargetName, testFileName, subpackage) } /** diff --git a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt index 3c764939468..32cbf21f084 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt @@ -379,23 +379,63 @@ class BazelClientTest { assertThat(thirdPartyDependenciesList).doesNotContain("@maven//:androidx_annotation_annotation") } - @Test + /*@Test fun testRunCodeCoverageForATestTarget() { -// val bazelClient = BazelClient(tempFolder.root, commandExecutor) + val bazelClient = BazelClient(tempFolder.root, commandExecutor) testBazelWorkspace.initEmptyWorkspace() - testBazelWorkspace.createTest("FirstTest") + //testBazelWorkspace.createTest("FirstTest") + // Verify the test file is created + *//*val testFile = File(tempFolder.root, "FirstTest.kt") + assertThat(testFile.exists()).isTrue() + assertThat(testFile.isFile).isTrue()*//* + + val sourceContent = """ + class SumTwoNumbers { + fun add(a: Int, b: Int): Int = a + b + } + """.trimIndent() + + val testContent = """ + import org.junit.Test + import com.google.common.truth.Truth.assertThat + + class SumTwoNumbersTest { + @Test + fun addTwoNumbers() { + val sumTwoNumbers = SumTwoNumbers() + assertThat(sumTwoNumbers.add(2, 3)).isEqualTo(5) + } + } + """.trimIndent() + + testBazelWorkspace.addSourceFileAndItsTestFileWithContent( + filename = "SumTwoNumbers", + sourceContent = sourceContent, + testContent = testContent, + subpackage = "coverage" + ) + + // Verify the source file is created + val sourceFile = File(tempFolder.root, "coverage/source/SumTwoNumbers.kt") + assertThat(sourceFile.exists()).isTrue() + assertThat(sourceFile.isFile).isTrue() + assertThat(sourceFile.readText()).isEqualTo(sourceContent) // Verify the test file is created - val testFile = File(tempFolder.root, "FirstTest.kt") + val testFile = File(tempFolder.root, "coverage/test/SumTwoNumbersTest.kt") assertThat(testFile.exists()).isTrue() assertThat(testFile.isFile).isTrue() + assertThat(testFile.readText()).isEqualTo(testContent) + + // Optionally, list all files and their contents for verification + println("Workspace directory structure and file contents:") + listFilesAndContents(tempFolder.root) - val addsource = testBazelWorkspace.addSourceFileAndItsTestFileWithContent("test1", "Hi", "@Test", "cc") - println("Add Source result: $addsource") + bazelClient.runCoverageForTestTarget("coverage/test:SumTwoNumbersTest") - listFilesInDirectory(tempFolder.root) -// bazelClient.runCoverageForTestTarget("//utility/src/test/java/org/oppia/android/util/parser/math:MathModelTest") + *//*listFilesInDirectory(tempFolder.root) + //bazelClient.runCoverageForTestTarget("//utility/src/test/java/org/oppia/android/util/parser/math:MathModelTest") // Verify the WORKSPACE file exists val workspaceFile = File(tempFolder.root, "WORKSPACE") @@ -406,15 +446,92 @@ class BazelClientTest { println("\nContents of WORKSPACE file:") println(workspaceFile.readText()) + // Verify the test file exists + val realtedTestFile = File(tempFolder.root, "/cc/source/test1.kt") + assertThat(realtedTestFile.exists()).isTrue() + assertThat(realtedTestFile.isFile).isTrue() + + // Print the contents of the test.bazel file + println("Contents of test file:") + println(realtedTestFile.readText()) + // Verify the BUILD.bazel file exists - val bazelFile = File(tempFolder.root, "BUILD.bazel") + val bazelFile = File(tempFolder.root, "/cc/test/BUILD.bazel") assertThat(bazelFile.exists()).isTrue() assertThat(bazelFile.isFile).isTrue() // Print the contents of the BUILD.bazel file - println("Contents of BUILD BAZEL file:") - println(bazelFile.readText()) + println("\nContents of BUILD BAZEL file:") + println(bazelFile.readText())*//* + }*/ + + @Test + fun testRunCodeCoverageForATestTarget() { + val bazelClient = BazelClient(tempFolder.root, commandExecutor) + testBazelWorkspace.initEmptyWorkspace() + + val sourceContent = """ + package com.example; + + public class Collatz { + + public static int getCollatzFinal(int n) { + if (n == 1) { + return 1; + } + if (n % 2 == 0) { + return getCollatzFinal(n / 2); + } else { + return getCollatzFinal(n * 3 + 1); + } + } + } + """.trimIndent() + + val testContent = """ + package com.example; + + import static org.junit.Assert.assertEquals; + import org.junit.Test; + + public class TestCollatz { + + @Test + public void testGetCollatzFinal() { + assertEquals(Collatz.getCollatzFinal(1), 1); + assertEquals(Collatz.getCollatzFinal(5), 1); + assertEquals(Collatz.getCollatzFinal(10), 1); + assertEquals(Collatz.getCollatzFinal(21), 1); + } + } + """.trimIndent() + + testBazelWorkspace.addSampleSourceAndTestFile( + filename = "Collatz", + sourceContent = sourceContent, + testContent = testContent, + subpackage = "coverage" + ) + listFilesAndContents(tempFolder.root) + + println("Temp dir: ${tempFolder}") + println("Temp root: ${tempFolder.root}") + println("Temp root: ${tempFolder.root}") + + val result = bazelClient.runCoverageForTestTarget("//coverage/test/java/com/example:test") + println("Result: $result") + } + + private fun listFilesAndContents(directory: File) { + directory.walk().forEach { file -> + if (file.isFile) { + println("File: ${file.relativeTo(directory)}") + println("Contents:\n${file.readText()}\n") + } else if (file.isDirectory) { + println("Directory: ${file.relativeTo(directory)}") + } + } } private fun listFilesInDirectory(directory: File) { From eb1e2746511d8056f0fbbc85b284b5ca65ac1f68 Mon Sep 17 00:00:00 2001 From: Rd Date: Sun, 9 Jun 2024 17:11:49 +0530 Subject: [PATCH 07/12] Added Test for BazelClient - for sample target and non target executions --- .../android/scripts/common/BazelClient.kt | 37 +-------- .../android/scripts/common/BazelClientTest.kt | 81 ++++++++++++++++++- 2 files changed, 82 insertions(+), 36 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt b/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt index cf198c10963..706adbba03c 100644 --- a/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt +++ b/scripts/src/java/org/oppia/android/scripts/common/BazelClient.kt @@ -136,44 +136,11 @@ class BazelClient(private val rootDirectory: File, private val commandExecutor: * @param bazelTestTarget Bazel test target for which code coverage will be run. * @return generated coverageResult output */ -// fun runCoverageForTestTarget(bazelTestTarget: String): List { - fun runCoverageForTestTarget(bazelTestTarget: String): String? { - /*return executeBazelCommand( - "coverage", - bazelTestTarget - )*/ - val result = executeBazelCommand( + fun runCoverageForTestTarget(bazelTestTarget: String): List { + return executeBazelCommand( "coverage", bazelTestTarget ) - - println("Coverage data from exe: $result") - val filedata = parseCoverageDataFile(result) - - println("Coverage data path from exe: $filedata") - val file = File(filedata) - - if (file.exists() && file.isFile) { - val contents = file.readText() - println(contents) - } else { - println("File does not exist or is not a valid file: $filedata") - } - - return filedata - } - - fun parseCoverageDataFile(data: List) : String? { - val regex = ".*coverage\\.dat$".toRegex() - for (line in data) { - val match = regex.find(line) - val extractedPath = match?.value?.substringAfterLast(",")?.trim() - if (extractedPath != null) { - println("Parsed Coverage Data File: $extractedPath") - return extractedPath - } - } - return null } /** diff --git a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt index 32cbf21f084..7394fbf8d1a 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt @@ -16,6 +16,12 @@ import org.oppia.android.testing.mockito.anyOrNull import java.io.File import java.util.concurrent.TimeUnit + + + + + + /** * Tests for [BazelClient]. * @@ -519,10 +525,83 @@ class BazelClientTest { println("Temp root: ${tempFolder.root}") println("Temp root: ${tempFolder.root}") - val result = bazelClient.runCoverageForTestTarget("//coverage/test/java/com/example:test") + val result = bazelClient.runCoverageForTestTarget("//coverage/test/java/com/example:test2") println("Result: $result") } + @Test + fun testRunCodeCoverage_forSampleTestTarget_returnsCoverageResult() { + val bazelClient = BazelClient(tempFolder.root, commandExecutor) + testBazelWorkspace.initEmptyWorkspace() + + val sourceContent = """ + package com.example; + + public class Collatz { + + public static int getCollatzFinal(int n) { + if (n == 1) { + return 1; + } + if (n % 2 == 0) { + return getCollatzFinal(n / 2); + } else { + return getCollatzFinal(n * 3 + 1); + } + } + } + """.trimIndent() + + val testContent = """ + package com.example; + + import static org.junit.Assert.assertEquals; + import org.junit.Test; + + public class TestCollatz { + + @Test + public void testGetCollatzFinal() { + assertEquals(Collatz.getCollatzFinal(1), 1); + assertEquals(Collatz.getCollatzFinal(5), 1); + assertEquals(Collatz.getCollatzFinal(10), 1); + assertEquals(Collatz.getCollatzFinal(21), 1); + } + } + """.trimIndent() + + testBazelWorkspace.addSampleSourceAndTestFile( + filename = "Collatz", + sourceContent = sourceContent, + testContent = testContent, + subpackage = "coverage" + ) + + val result = bazelClient.runCoverageForTestTarget("//coverage/test/java/com/example:test") + + // Check that the test has "PASSED" + val containsPassedValue = result.any { it.contains("PASSED") } + assert(containsPassedValue) { "The test is not 'PASSED'" } + + // Check if the coverage.dat file is generated + val containsCoverageData = result.any { it.contains("coverage.dat") } + assert(containsCoverageData) { "The coverage.dat is not generated" } + } + + @Test + fun testRunCodeCoverage_forNonTestTarget_fails() { + val bazelClient = BazelClient(tempFolder.root, commandExecutor) + testBazelWorkspace.initEmptyWorkspace() + + val exception = assertThrows() { + bazelClient.runCoverageForTestTarget("//coverage/test/java/com/example:test") + } + + // Verify that the underlying Bazel command failed since the test target was not available. + assertThat(exception).hasMessageThat().contains("Expected non-zero exit code") + assertThat(exception).hasMessageThat().contains("no such package") + } + private fun listFilesAndContents(directory: File) { directory.walk().forEach { file -> if (file.isFile) { From 0e68746186343213d93a25bb8cad5a8f053c44b1 Mon Sep 17 00:00:00 2001 From: Rd Date: Tue, 11 Jun 2024 00:46:15 +0530 Subject: [PATCH 08/12] Added Coverage Runner functionality tests --- .../scripts/coverage/CoverageRunner.kt | 22 ++- .../coverage/RunCoverageForTestTarget.kt | 15 +- .../android/scripts/coverage/BUILD.bazel | 17 +++ .../scripts/coverage/CoverageRunnerTest.kt | 138 ++++++++++++++++++ 4 files changed, 174 insertions(+), 18 deletions(-) create mode 100644 scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel create mode 100644 scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt index ffd286b160c..79623f6472b 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt @@ -7,12 +7,16 @@ import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.async import kotlinx.coroutines.Deferred +import kotlinx.coroutines.withContext import java.io.File /** * Class responsible for running coverage analysis asynchronously. */ -class CoverageRunner { +class CoverageRunner( + private val repoRoot: File, + private val scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher + ) { /** * Runs coverage analysis asynchronously for the Bazel test target. @@ -23,13 +27,11 @@ class CoverageRunner { * @return a deferred value that contains the path of the coverage data file [will contain the proto for the coverage data]. */ suspend fun runWithCoverageAsync( - repoRoot: File, - scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher, bazelTestTarget: String ): Deferred { return CoroutineScope(scriptBgDispatcher).async { - val coverageData = getCoverage(repoRoot, scriptBgDispatcher, bazelTestTarget) - val data = coverageData.await() + val coverageData = getCoverage(bazelTestTarget) + val data = coverageData parseCoverageDataFile(data) } } @@ -40,19 +42,15 @@ class CoverageRunner { * @param repoRoot the absolute path to the working root directory * @param scriptBgDispatcher the [ScriptBackgroundCoroutineDispatcher] to be used for running the coverage command * @param bazelTestTarget Bazel test target to analyze coverage. - * @return a deferred value that contains the result of the coverage execution. + * @return a lisf of string that contains the result of the coverage execution. */ fun getCoverage( - repoRoot: File, - scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher, bazelTestTarget: String - ): Deferred> { - return CoroutineScope(scriptBgDispatcher).async { + ): List { val commandExecutor: CommandExecutor = CommandExecutorImpl(scriptBgDispatcher) val bazelClient = BazelClient(repoRoot, commandExecutor) val coverageData = bazelClient.runCoverageForTestTarget(bazelTestTarget) - coverageData - } + return coverageData } /** diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt index f57d798c4d1..51dc65a7031 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -14,13 +14,16 @@ fun main(vararg args: String) { val repoRoot = File(args[0]).absoluteFile.normalize() val targetPath = args[1] - RunCoverageForTestTarget().runCoverage(repoRoot, targetPath) + RunCoverageForTestTarget(repoRoot, targetPath).runCoverage() } /** * Class responsible for analyzing target files for coverage and generating reports. */ -class RunCoverageForTestTarget() { +class RunCoverageForTestTarget( + private val repoRoot: File, + private val targetPath : String +) { /** * Analyzes target file for coverage, generates chosen reports accordingly. @@ -28,8 +31,8 @@ class RunCoverageForTestTarget() { * @param repoRoot the absolute path to the working root directory * @param targetFile Path to the file to analyze. */ - fun runCoverage(repoRoot: File, targetPath: String) { - runWithCoverageAnalysis(repoRoot, targetPath) + fun runCoverage() { + runWithCoverageAnalysis() } /** @@ -39,10 +42,10 @@ class RunCoverageForTestTarget() { * @param targetFile Path to the target file to analyze coverage. * @return [A deferred result representing the coverage report]. */ - fun runWithCoverageAnalysis(repoRoot: File, targetPath: String) { + fun runWithCoverageAnalysis() { ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher -> runBlocking { - CoverageRunner().runWithCoverageAsync(repoRoot, scriptBgDispatcher, targetPath).await() + CoverageRunner(repoRoot, scriptBgDispatcher).runWithCoverageAsync(targetPath).await() } } } diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel b/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel new file mode 100644 index 00000000000..f2e5c80564b --- /dev/null +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel @@ -0,0 +1,17 @@ +""" +Tests corresponding to developer scripts that help with obtaining coverage data for test targets. +""" + +load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") + +kt_jvm_test( + name = "CoverageRunnerTest", + srcs = ["CoverageRunnerTest.kt"], + deps = [ + "//scripts/src/java/org/oppia/android/scripts/coverage:coverage_runner", + "//scripts/src/java/org/oppia/android/scripts/testing:test_bazel_workspace", + "//testing:assertion_helpers", + "//third_party:com_google_truth_truth", + "//third_party:org_jetbrains_kotlin_kotlin-test-junit", + ], +) diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt new file mode 100644 index 00000000000..52ba07a6fe9 --- /dev/null +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt @@ -0,0 +1,138 @@ +package org.oppia.android.scripts.coverage + +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher +import org.oppia.android.testing.assertThrows +import org.oppia.android.scripts.testing.TestBazelWorkspace +import kotlin.test.assertEquals +import java.io.File + +class CoverageRunnerTest { + @field:[Rule JvmField] val tempFolder = TemporaryFolder() + + private val scriptBgDispatcher by lazy { ScriptBackgroundCoroutineDispatcher() } + + private lateinit var coverageRunner: CoverageRunner + private lateinit var testBazelWorkspace: TestBazelWorkspace + private lateinit var bazelTestTarget: String + + @Before + fun setUp() { + coverageRunner = CoverageRunner(tempFolder.root, scriptBgDispatcher) + bazelTestTarget = "//:testTarget" + testBazelWorkspace = TestBazelWorkspace(tempFolder) + } + + @After + fun tearDown() { + scriptBgDispatcher.close() + } + + @Test + fun testParseCoverageDataFile_invalidData_returnsNull() { + // Result data from coverage execution that doesn't contain path to coverage data file [coverage.dat] + val invalidResultData = listOf("data1", "data2", "data3") + + val parsedData = coverageRunner.parseCoverageDataFile(invalidResultData) + // Return Null when the coverage data file path is not found + assertThat(parsedData).isNull() + } + + @Test + fun testParseCoverageDataFile_validData_returnsNull() { + // Result data from coverage execution that contains path to coverage data file [coverage.dat] + val validResultData = listOf( + "//package/test/example:test PASSED in 0.4s", + "/path/.cache/bazel/4654367352564/sandbox/__main__/__tmp/coverage/package/test/coverage.dat", + "Executed 1 out of 1 test: 1 test passes." + ) + val expectedResultParsedData = "/path/.cache/bazel/4654367352564/sandbox/__main__/__tmp/coverage/package/test/coverage.dat" + + val parsedData = coverageRunner.parseCoverageDataFile(validResultData) + assertThat(parsedData).isEqualTo(expectedResultParsedData) + } + + @Test + fun testRunCoverage_emptyDirectory_throwsException() { + val exception = assertThrows() { + coverageRunner.getCoverage(bazelTestTarget) + } + + assertThat(exception).hasMessageThat().contains("not invoked from within a workspace") + } + + @Test + fun testRunCoverage_invalidTestTarget_throwsException() { + testBazelWorkspace.initEmptyWorkspace() + + val exception = assertThrows() { + coverageRunner.getCoverage(bazelTestTarget) + } + + assertThat(exception).hasMessageThat().contains("Expected non-zero exit code") + assertThat(exception).hasMessageThat().contains("no such package") + } + + @Test + fun testRunCoverage_validSampleTestTarget_returnsCoverageData() { + testBazelWorkspace.initEmptyWorkspace() + + val sourceContent = """ + package com.example; + + public class Collatz { + + public static int getCollatzFinal(int n) { + if (n == 1) { + return 1; + } + if (n % 2 == 0) { + return getCollatzFinal(n / 2); + } else { + return getCollatzFinal(n * 3 + 1); + } + } + } + """.trimIndent() + + val testContent = """ + package com.example; + + import static org.junit.Assert.assertEquals; + import org.junit.Test; + + public class TestCollatz { + + @Test + public void testGetCollatzFinal() { + assertEquals(Collatz.getCollatzFinal(1), 1); + assertEquals(Collatz.getCollatzFinal(5), 1); + assertEquals(Collatz.getCollatzFinal(10), 1); + assertEquals(Collatz.getCollatzFinal(21), 1); + } + } + """.trimIndent() + + testBazelWorkspace.addSampleSourceAndTestFile( + filename = "Collatz", + sourceContent = sourceContent, + testContent = testContent, + subpackage = "coverage" + ) + + val result = coverageRunner.getCoverage("//coverage/test/java/com/example:test") + + // Check that the test has "PASSED" + val containsPassedValue = result.any { it.contains("PASSED") } + assert(containsPassedValue) { "The test is not 'PASSED'" } + + // Check if the coverage.dat file is generated + val containsCoverageData = result.any { it.contains("coverage.dat") } + assert(containsCoverageData) { "The coverage.dat is not generated" } + } +} From 79d73b29a63dbd5a89976abc162d6513e7b13480 Mon Sep 17 00:00:00 2001 From: Rd Date: Tue, 11 Jun 2024 22:17:18 +0530 Subject: [PATCH 09/12] Added tests for the RunCoverageForTestTarget utility --- .../scripts/coverage/CoverageRunner.kt | 3 + .../coverage/RunCoverageForTestTarget.kt | 30 +++-- .../android/scripts/coverage/BUILD.bazel | 12 ++ .../scripts/coverage/CoverageRunnerTest.kt | 1 + .../coverage/RunCoverageForTestTargetTest.kt | 116 ++++++++++++++++++ 5 files changed, 150 insertions(+), 12 deletions(-) create mode 100644 scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt index 79623f6472b..3210ae4c978 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt @@ -12,6 +12,9 @@ import java.io.File /** * Class responsible for running coverage analysis asynchronously. + * + * @param repoRoot the absolute path to the working root directory + * @param targetFile Path to the target file to analyze coverage. */ class CoverageRunner( private val repoRoot: File, diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt index 51dc65a7031..07477fa1a48 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -8,7 +8,16 @@ import java.io.File /** * Entry point function for running coverage analysis for a single test target. * - * @param args Command-line arguments. + * Usage: + * bazel run //scripts:run_coverage_for_test_target -- + * + * Arguments: + * - path_to_root: directory path to the root of the Oppia Android repository. + * - test_targetname: bazel target name of the test + * + * Example: + * bazel run //scripts:run_coverage_for_test_target -- $(pwd) + * //utility/src/test/java/org/oppia/android/util/parser/math:MathModelTest */ fun main(vararg args: String) { val repoRoot = File(args[0]).absoluteFile.normalize() @@ -27,25 +36,22 @@ class RunCoverageForTestTarget( /** * Analyzes target file for coverage, generates chosen reports accordingly. - * - * @param repoRoot the absolute path to the working root directory - * @param targetFile Path to the file to analyze. */ - fun runCoverage() { - runWithCoverageAnalysis() + fun runCoverage(): String? { + return runWithCoverageAnalysis() } /** * Runs coverage analysis on the specified target file asynchronously. * - * @param repoRoot the absolute path to the working root directory - * @param targetFile Path to the target file to analyze coverage. - * @return [A deferred result representing the coverage report]. + * @return [Path of the coverage data file]. */ - fun runWithCoverageAnalysis() { - ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher -> + fun runWithCoverageAnalysis(): String? { + return ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher -> runBlocking { - CoverageRunner(repoRoot, scriptBgDispatcher).runWithCoverageAsync(targetPath).await() + val result = + CoverageRunner(repoRoot, scriptBgDispatcher).runWithCoverageAsync(targetPath).await() + result } } } diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel b/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel index f2e5c80564b..cb20129dd61 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/BUILD.bazel @@ -15,3 +15,15 @@ kt_jvm_test( "//third_party:org_jetbrains_kotlin_kotlin-test-junit", ], ) + +kt_jvm_test( + name = "RunCoverageForTestTargetTest", + srcs = ["RunCoverageForTestTargetTest.kt"], + deps = [ + "//scripts/src/java/org/oppia/android/scripts/coverage:run_coverage_for_test_target_lib", + "//scripts/src/java/org/oppia/android/scripts/testing:test_bazel_workspace", + "//testing:assertion_helpers", + "//third_party:com_google_truth_truth", + "//third_party:org_jetbrains_kotlin_kotlin-test-junit", + ], +) diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt index 52ba07a6fe9..d88d3d5e03b 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt @@ -12,6 +12,7 @@ import org.oppia.android.scripts.testing.TestBazelWorkspace import kotlin.test.assertEquals import java.io.File +/** Tests for [CoverageRunner] */ class CoverageRunnerTest { @field:[Rule JvmField] val tempFolder = TemporaryFolder() diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt new file mode 100644 index 00000000000..c2c1a9d47ef --- /dev/null +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt @@ -0,0 +1,116 @@ +package org.oppia.android.scripts.coverage + +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher +import org.oppia.android.scripts.testing.TestBazelWorkspace +import org.oppia.android.testing.assertThrows + +/** Tests for [RunCoverageForTestTarget] */ +class RunCoverageForTestTargetTest { + @field:[Rule JvmField] val tempFolder = TemporaryFolder() + + private val scriptBgDispatcher by lazy { ScriptBackgroundCoroutineDispatcher() } + + private lateinit var testBazelWorkspace: TestBazelWorkspace + private lateinit var bazelTestTarget: String + + @Before + fun setUp() { + bazelTestTarget = "//:testTarget" + testBazelWorkspace = TestBazelWorkspace(tempFolder) + } + + @After + fun tearDown() { + scriptBgDispatcher.close() + } + + @Test + fun testRunCoverageForTestTarget_emptyDirectory_throwsException() { + val exception = assertThrows() { + RunCoverageForTestTarget( + tempFolder.root, + bazelTestTarget + ).runCoverage() + } + + assertThat(exception).hasMessageThat().contains("not invoked from within a workspace") + } + + @Test + fun testRunCoverageForTestTarget_invalidTestTarget_throwsException() { + testBazelWorkspace.initEmptyWorkspace() + + val exception = assertThrows() { + RunCoverageForTestTarget( + tempFolder.root, + bazelTestTarget + ).runCoverage() + } + + assertThat(exception).hasMessageThat().contains("Expected non-zero exit code") + assertThat(exception).hasMessageThat().contains("no such package") + } + + @Test + fun testRunCoverageForTestTarget_validSampleTestTarget_returnsCoverageDataPath() { + testBazelWorkspace.initEmptyWorkspace() + + val sourceContent = """ + package com.example; + + public class Collatz { + + public static int getCollatzFinal(int n) { + if (n == 1) { + return 1; + } + if (n % 2 == 0) { + return getCollatzFinal(n / 2); + } else { + return getCollatzFinal(n * 3 + 1); + } + } + } + """.trimIndent() + + val testContent = """ + package com.example; + + import static org.junit.Assert.assertEquals; + import org.junit.Test; + + public class TestCollatz { + + @Test + public void testGetCollatzFinal() { + assertEquals(Collatz.getCollatzFinal(1), 1); + assertEquals(Collatz.getCollatzFinal(5), 1); + assertEquals(Collatz.getCollatzFinal(10), 1); + assertEquals(Collatz.getCollatzFinal(21), 1); + } + } + """.trimIndent() + + testBazelWorkspace.addSampleSourceAndTestFile( + filename = "Collatz", + sourceContent = sourceContent, + testContent = testContent, + subpackage = "coverage" + ) + + val result = RunCoverageForTestTarget( + tempFolder.root, + "//coverage/test/java/com/example:test" + ).runCoverage() + + // Check if the coverage.dat file is generated and parsed as result + val parsedCoverageDataPath = result?.endsWith("coverage.dat") + assert(parsedCoverageDataPath!!) { "The coverage.dat is not generated" } + } +} \ No newline at end of file From 2d51176796f60c948546fa11f03b46cd0b99061a Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 13 Jun 2024 09:45:46 +0530 Subject: [PATCH 10/12] Replaced Java Test Sources with Kotlin Sources --- .../scripts/testing/TestBazelWorkspace.kt | 188 +++------------ .../android/scripts/common/BazelClientTest.kt | 217 +++--------------- .../scripts/coverage/CoverageRunnerTest.kt | 56 +++-- .../coverage/RunCoverageForTestTargetTest.kt | 56 +++-- 4 files changed, 110 insertions(+), 407 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt index b489f708b8f..14ceac6ed9c 100644 --- a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt +++ b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt @@ -50,95 +50,18 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { assertThat(bazelRcFile.exists()).isTrue() } - fun addSampleSourceAndTestFile( + fun addSourceAndTestFileWithContent( filename: String, sourceContent: String, testContent: String, subpackage: String ) { val sourceSubpackage = "$subpackage/main/java/com/example" - addSampleSourceContentAndBuildFile(filename, sourceContent, sourceSubpackage) + addSourceContentAndBuildFile(filename, sourceContent, sourceSubpackage) val testSubpackage = "$subpackage/test/java/com/example" - val testFileName = "Test${filename}" - addSampleTestContentAndBuildFile(testFileName, testContent, testSubpackage) - } - - fun addSampleSourceContentAndBuildFile( - filename: String, - sourceContent: String, - sourceSubpackage: String - ) { - initEmptyWorkspace() - - // Create the source subpackage directory if it doesn't exist - if (!File(temporaryRootFolder.root, sourceSubpackage.replace(".", "/")).exists()) { - temporaryRootFolder.newFolder(*(sourceSubpackage.split(".")).toTypedArray()) - } - - // Create the source file - val sourceFile = temporaryRootFolder.newFile("${sourceSubpackage.replace(".", "/")}/$filename.java") - sourceFile.writeText(sourceContent) - - // Create or update the BUILD file for the source file - val buildFileRelativePath = "${sourceSubpackage.replace(".", "/")}/BUILD.bazel" - val buildFile = File(temporaryRootFolder.root, buildFileRelativePath) - if (!buildFile.exists()) { - temporaryRootFolder.newFile(buildFileRelativePath) - } - - //prepareBuildFileForLibraries(buildFile) - - //val libTargetName = "//${sourceSubpackage}:${filename}_lib" - buildFile.appendText( - """ - package( - default_visibility = ["//visibility:public"], - ) - - java_library( - name = "collatz_lib", - srcs=["Collatz.java"], - ) - """.trimIndent() + "\n" - ) - } - - fun addSampleTestContentAndBuildFile( - testName: String, - testContent: String, - testSubpackage: String - ) { - initEmptyWorkspace() - - // Create the test subpackage directory for the test file if it doesn't exist - if (!File(temporaryRootFolder.root, testSubpackage.replace(".", "/")).exists()) { - temporaryRootFolder.newFolder(*(testSubpackage.split(".")).toTypedArray()) - } - - // Create the test file - val testFile = temporaryRootFolder.newFile("${testSubpackage.replace(".", "/")}/$testName.java") - testFile.writeText(testContent) - - // Create or update the BUILD file for the test file - val testBuildFileRelativePath = "${testSubpackage.replace(".", "/")}/BUILD.bazel" - val testBuildFile = File(temporaryRootFolder.root, testBuildFileRelativePath) - if (!testBuildFile.exists()) { - temporaryRootFolder.newFile(testBuildFileRelativePath) - } - //prepareBuildFileForTests(testBuildFile) - - // Add the test file to the BUILD file with appropriate dependencies - testBuildFile.appendText( - """ - java_test( - name = "test", - srcs = ["TestCollatz.java"], - test_class = "com.example.TestCollatz", - deps = ["//coverage/main/java/com/example:collatz_lib"], - ) - """.trimIndent() + "\n" - ) + val testFileName = "${filename}Test" + addTestContentAndBuildFile(filename, testFileName, testContent, testSubpackage) } /** @@ -147,16 +70,19 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { * * @param filename the name of the source file (without the .kt extension) * @param sourceContent the content of the source file - * @param subpackage the subpackage under which the source file should be added + * @param sourceSubpackage the subpackage under which the source file should be added * @return the target name of the added source file */ fun addSourceContentAndBuildFile( filename: String, sourceContent: String, sourceSubpackage: String - ): String { - initEmptyWorkspace() // Ensure the workspace is at least initialized. + ) { + initEmptyWorkspace() ensureWorkspaceIsConfiguredForKotlin() + setUpWorkspaceForRulesJvmExternal( + listOf("junit:junit:4.12") + ) // Create the source subpackage directory if it doesn't exist if (!File(temporaryRootFolder.root, sourceSubpackage.replace(".", "/")).exists()) { @@ -174,37 +100,36 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { temporaryRootFolder.newFile(buildFileRelativePath) } - prepareBuildFileForLibraries(buildFile) - - val libTargetName = "//${sourceSubpackage}:${filename}_lib" buildFile.appendText( """ + load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_library") + kt_jvm_library( - name = "${filename}_lib", - srcs=["$filename}.kt"], + name = "${filename.lowercase()}", + srcs = ["${filename}.kt"], + visibility = ["//visibility:public"], + deps = [], ) """.trimIndent() + "\n" ) - return libTargetName } /** * Adds a test file with the specified name and content to the specified subpackage, * and updates the corresponding build configuration. * + * @param filename the name of the source file (without the .kt extension) * @param testName the name of the test file (without the .kt extension) * @param testContent the content of the test file - * @param libTargetName the target name of the library the test depends on * @param testSubpackage the subpackage for the test file */ fun addTestContentAndBuildFile( + filename: String, testName: String, testContent: String, - libTargetName: String, testSubpackage: String ) { - initEmptyWorkspace() // Ensure the workspace is at least initialized. - ensureWorkspaceIsConfiguredForKotlin() + initEmptyWorkspace() // Create the test subpackage directory for the test file if it doesn't exist if (!File(temporaryRootFolder.root, testSubpackage.replace(".", "/")).exists()) { @@ -221,81 +146,26 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { if (!testBuildFile.exists()) { temporaryRootFolder.newFile(testBuildFileRelativePath) } - prepareBuildFileForTests(testBuildFile) // Add the test file to the BUILD file with appropriate dependencies testBuildFile.appendText( """ + load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test") + kt_jvm_test( - name = "$testName", - srcs = ["${testName}.kt"], - deps = [ - "@maven//:junit_junit", - "$libTargetName", - ], + name = "test", + srcs = ["${testName}.kt"], + deps = [ + "//coverage/main/java/com/example:${filename.lowercase()}", + "@maven//:junit_junit", + ], + visibility = ["//visibility:public"], + test_class = "com.example.${testName}", ) """.trimIndent() + "\n" ) } - fun setupGeneralCoverageBuildFile( - sourceLibTargetName: String, - testTargetName: String, - coverageSubpackage: String - ) { - initEmptyWorkspace() // Ensure the workspace is at least initialized. - ensureWorkspaceIsConfiguredForKotlin() // Ensure Kotlin rules are set up. - - // Create the coverage subpackage directory if it doesn't exist - if (!File(temporaryRootFolder.root, coverageSubpackage.replace(".", "/")).exists()) { - temporaryRootFolder.newFolder(*(coverageSubpackage.split(".")).toTypedArray()) - } - - // Create or update the BUILD file for the coverage package - val coverageBuildFileRelativePath = "${coverageSubpackage.replace(".", "/")}/BUILD.bazel" - val coverageBuildFile = File(temporaryRootFolder.root, coverageBuildFileRelativePath) - if (!coverageBuildFile.exists()) { - temporaryRootFolder.newFile(coverageBuildFileRelativePath) - } - - coverageBuildFile.appendText( - """ - kt_jvm_binary( - name = "coverage_runner", - srcs = ["//${coverageSubpackage.replace(".", "/")}:$testTargetName"], - deps = [ - "$sourceLibTargetName", - ], - ) - """.trimIndent() + "\n" - ) - } - - /** - * Adds a file with the specified name and content, along with its corresponding test file and - * test content, to the specified subpackage. Ensures the appropriate build configurations are created. - * - * @param filename the name of the source file (without the .kt extension) - * @param sourceContent the content of the source file - * @param testContent the content of the test file - * @param subpackage the subpackage for the source and test files - */ - fun addSourceFileAndItsTestFileWithContent( - filename: String, - sourceContent: String, - testContent: String, - subpackage: String, - ) { - val sourceSubpackage = "$subpackage/source" - val libTargetName = addSourceContentAndBuildFile(filename, sourceContent, sourceSubpackage) - - val testSubpackage = "$subpackage/test" - val testFileName = "${filename}Test" - addTestContentAndBuildFile(testFileName, testContent, libTargetName, testSubpackage) - - setupGeneralCoverageBuildFile(libTargetName, testFileName, subpackage) - } - /** * Generates and adds a new kt_jvm_test target with the target name [testName] and test file * [testFile]. This can be used to add multiple tests to the same build file, and will diff --git a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt index 7394fbf8d1a..a6560782a06 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt @@ -385,193 +385,47 @@ class BazelClientTest { assertThat(thirdPartyDependenciesList).doesNotContain("@maven//:androidx_annotation_annotation") } - /*@Test - fun testRunCodeCoverageForATestTarget() { - val bazelClient = BazelClient(tempFolder.root, commandExecutor) - testBazelWorkspace.initEmptyWorkspace() - //testBazelWorkspace.createTest("FirstTest") - - // Verify the test file is created - *//*val testFile = File(tempFolder.root, "FirstTest.kt") - assertThat(testFile.exists()).isTrue() - assertThat(testFile.isFile).isTrue()*//* - - val sourceContent = """ - class SumTwoNumbers { - fun add(a: Int, b: Int): Int = a + b - } - """.trimIndent() - - val testContent = """ - import org.junit.Test - import com.google.common.truth.Truth.assertThat - - class SumTwoNumbersTest { - @Test - fun addTwoNumbers() { - val sumTwoNumbers = SumTwoNumbers() - assertThat(sumTwoNumbers.add(2, 3)).isEqualTo(5) - } - } - """.trimIndent() - - testBazelWorkspace.addSourceFileAndItsTestFileWithContent( - filename = "SumTwoNumbers", - sourceContent = sourceContent, - testContent = testContent, - subpackage = "coverage" - ) - - // Verify the source file is created - val sourceFile = File(tempFolder.root, "coverage/source/SumTwoNumbers.kt") - assertThat(sourceFile.exists()).isTrue() - assertThat(sourceFile.isFile).isTrue() - assertThat(sourceFile.readText()).isEqualTo(sourceContent) - - // Verify the test file is created - val testFile = File(tempFolder.root, "coverage/test/SumTwoNumbersTest.kt") - assertThat(testFile.exists()).isTrue() - assertThat(testFile.isFile).isTrue() - assertThat(testFile.readText()).isEqualTo(testContent) - - // Optionally, list all files and their contents for verification - println("Workspace directory structure and file contents:") - listFilesAndContents(tempFolder.root) - - bazelClient.runCoverageForTestTarget("coverage/test:SumTwoNumbersTest") - - *//*listFilesInDirectory(tempFolder.root) - //bazelClient.runCoverageForTestTarget("//utility/src/test/java/org/oppia/android/util/parser/math:MathModelTest") - - // Verify the WORKSPACE file exists - val workspaceFile = File(tempFolder.root, "WORKSPACE") - assertThat(workspaceFile.exists()).isTrue() - assertThat(workspaceFile.isFile).isTrue() - - // Print the contents of the WORKSPACE file - println("\nContents of WORKSPACE file:") - println(workspaceFile.readText()) - - // Verify the test file exists - val realtedTestFile = File(tempFolder.root, "/cc/source/test1.kt") - assertThat(realtedTestFile.exists()).isTrue() - assertThat(realtedTestFile.isFile).isTrue() - - // Print the contents of the test.bazel file - println("Contents of test file:") - println(realtedTestFile.readText()) - - // Verify the BUILD.bazel file exists - val bazelFile = File(tempFolder.root, "/cc/test/BUILD.bazel") - assertThat(bazelFile.exists()).isTrue() - assertThat(bazelFile.isFile).isTrue() - - // Print the contents of the BUILD.bazel file - println("\nContents of BUILD BAZEL file:") - println(bazelFile.readText())*//* - }*/ - - @Test - fun testRunCodeCoverageForATestTarget() { - val bazelClient = BazelClient(tempFolder.root, commandExecutor) - testBazelWorkspace.initEmptyWorkspace() - - val sourceContent = """ - package com.example; - - public class Collatz { - - public static int getCollatzFinal(int n) { - if (n == 1) { - return 1; - } - if (n % 2 == 0) { - return getCollatzFinal(n / 2); - } else { - return getCollatzFinal(n * 3 + 1); - } - } - } - """.trimIndent() - - val testContent = """ - package com.example; - - import static org.junit.Assert.assertEquals; - import org.junit.Test; - - public class TestCollatz { - - @Test - public void testGetCollatzFinal() { - assertEquals(Collatz.getCollatzFinal(1), 1); - assertEquals(Collatz.getCollatzFinal(5), 1); - assertEquals(Collatz.getCollatzFinal(10), 1); - assertEquals(Collatz.getCollatzFinal(21), 1); - } - } - """.trimIndent() - - testBazelWorkspace.addSampleSourceAndTestFile( - filename = "Collatz", - sourceContent = sourceContent, - testContent = testContent, - subpackage = "coverage" - ) - - listFilesAndContents(tempFolder.root) - - println("Temp dir: ${tempFolder}") - println("Temp root: ${tempFolder.root}") - println("Temp root: ${tempFolder.root}") - - val result = bazelClient.runCoverageForTestTarget("//coverage/test/java/com/example:test2") - println("Result: $result") - } - @Test fun testRunCodeCoverage_forSampleTestTarget_returnsCoverageResult() { val bazelClient = BazelClient(tempFolder.root, commandExecutor) testBazelWorkspace.initEmptyWorkspace() val sourceContent = """ - package com.example; - - public class Collatz { - - public static int getCollatzFinal(int n) { - if (n == 1) { - return 1; - } - if (n % 2 == 0) { - return getCollatzFinal(n / 2); - } else { - return getCollatzFinal(n * 3 + 1); - } + package com.example + + class TwoSum { + + companion object { + fun sumNumbers(a: Int, b: Int): Any { + return if (a ==0 && b == 0) { + "Both numbers are zero" + } else { + a + b + } + } } - } + } """.trimIndent() val testContent = """ - package com.example; - - import static org.junit.Assert.assertEquals; - import org.junit.Test; - - public class TestCollatz { - + package com.example + + import org.junit.Assert.assertEquals + import org.junit.Test + + class TwoSumTest { + @Test - public void testGetCollatzFinal() { - assertEquals(Collatz.getCollatzFinal(1), 1); - assertEquals(Collatz.getCollatzFinal(5), 1); - assertEquals(Collatz.getCollatzFinal(10), 1); - assertEquals(Collatz.getCollatzFinal(21), 1); + fun testSumNumbers() { + assertEquals(TwoSum.sumNumbers(0, 1), 1) + assertEquals(TwoSum.sumNumbers(3, 4), 7) + assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") } - } + } """.trimIndent() - testBazelWorkspace.addSampleSourceAndTestFile( - filename = "Collatz", + testBazelWorkspace.addSourceAndTestFileWithContent( + filename = "TwoSum", sourceContent = sourceContent, testContent = testContent, subpackage = "coverage" @@ -602,23 +456,6 @@ class BazelClientTest { assertThat(exception).hasMessageThat().contains("no such package") } - private fun listFilesAndContents(directory: File) { - directory.walk().forEach { file -> - if (file.isFile) { - println("File: ${file.relativeTo(directory)}") - println("Contents:\n${file.readText()}\n") - } else if (file.isDirectory) { - println("Directory: ${file.relativeTo(directory)}") - } - } - } - - private fun listFilesInDirectory(directory: File) { - directory.walk().forEach { - println(it.relativeTo(directory)) - } - } - private fun fakeCommandExecutorWithResult(singleLine: String) { // Fake a Bazel command's results to return jumbled results. This has been observed to happen // sometimes in CI, but doesn't have a known cause. The utility is meant to de-jumble these in diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt index d88d3d5e03b..083fb870bd4 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt @@ -84,43 +84,41 @@ class CoverageRunnerTest { testBazelWorkspace.initEmptyWorkspace() val sourceContent = """ - package com.example; - - public class Collatz { - - public static int getCollatzFinal(int n) { - if (n == 1) { - return 1; - } - if (n % 2 == 0) { - return getCollatzFinal(n / 2); - } else { - return getCollatzFinal(n * 3 + 1); - } + package com.example + + class TwoSum { + + companion object { + fun sumNumbers(a: Int, b: Int): Any { + return if (a ==0 && b == 0) { + "Both numbers are zero" + } else { + a + b + } + } } - } + } """.trimIndent() val testContent = """ - package com.example; - - import static org.junit.Assert.assertEquals; - import org.junit.Test; - - public class TestCollatz { - + package com.example + + import org.junit.Assert.assertEquals + import org.junit.Test + + class TwoSumTest { + @Test - public void testGetCollatzFinal() { - assertEquals(Collatz.getCollatzFinal(1), 1); - assertEquals(Collatz.getCollatzFinal(5), 1); - assertEquals(Collatz.getCollatzFinal(10), 1); - assertEquals(Collatz.getCollatzFinal(21), 1); + fun testSumNumbers() { + assertEquals(TwoSum.sumNumbers(0, 1), 1) + assertEquals(TwoSum.sumNumbers(3, 4), 7) + assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") } - } + } """.trimIndent() - testBazelWorkspace.addSampleSourceAndTestFile( - filename = "Collatz", + testBazelWorkspace.addSourceAndTestFileWithContent( + filename = "TwoSum", sourceContent = sourceContent, testContent = testContent, subpackage = "coverage" diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt index c2c1a9d47ef..9c28fd9a4b2 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt @@ -62,43 +62,41 @@ class RunCoverageForTestTargetTest { testBazelWorkspace.initEmptyWorkspace() val sourceContent = """ - package com.example; - - public class Collatz { - - public static int getCollatzFinal(int n) { - if (n == 1) { - return 1; - } - if (n % 2 == 0) { - return getCollatzFinal(n / 2); - } else { - return getCollatzFinal(n * 3 + 1); - } + package com.example + + class TwoSum { + + companion object { + fun sumNumbers(a: Int, b: Int): Any { + return if (a ==0 && b == 0) { + "Both numbers are zero" + } else { + a + b + } + } } - } + } """.trimIndent() val testContent = """ - package com.example; - - import static org.junit.Assert.assertEquals; - import org.junit.Test; - - public class TestCollatz { - + package com.example + + import org.junit.Assert.assertEquals + import org.junit.Test + + class TwoSumTest { + @Test - public void testGetCollatzFinal() { - assertEquals(Collatz.getCollatzFinal(1), 1); - assertEquals(Collatz.getCollatzFinal(5), 1); - assertEquals(Collatz.getCollatzFinal(10), 1); - assertEquals(Collatz.getCollatzFinal(21), 1); + fun testSumNumbers() { + assertEquals(TwoSum.sumNumbers(0, 1), 1) + assertEquals(TwoSum.sumNumbers(3, 4), 7) + assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") } - } + } """.trimIndent() - testBazelWorkspace.addSampleSourceAndTestFile( - filename = "Collatz", + testBazelWorkspace.addSourceAndTestFileWithContent( + filename = "TwoSum", sourceContent = sourceContent, testContent = testContent, subpackage = "coverage" From fbd5084f307b5461e7ce2f77d25912fbf0d4ee85 Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 13 Jun 2024 11:13:58 +0530 Subject: [PATCH 11/12] Fix Static Checks / Lint warnings --- .../scripts/coverage/CoverageRunner.kt | 23 +++--- .../coverage/RunCoverageForTestTarget.kt | 5 +- .../scripts/testing/TestBazelWorkspace.kt | 19 ++++- .../android/scripts/common/BazelClientTest.kt | 74 +++++++++--------- .../scripts/coverage/CoverageRunnerTest.kt | 75 ++++++++++--------- .../coverage/RunCoverageForTestTargetTest.kt | 70 ++++++++--------- 6 files changed, 137 insertions(+), 129 deletions(-) diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt index 3210ae4c978..a88e4b6f0a5 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/CoverageRunner.kt @@ -1,13 +1,12 @@ package org.oppia.android.scripts.coverage +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.async import org.oppia.android.scripts.common.BazelClient import org.oppia.android.scripts.common.CommandExecutor import org.oppia.android.scripts.common.CommandExecutorImpl import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.async -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.withContext import java.io.File /** @@ -17,9 +16,9 @@ import java.io.File * @param targetFile Path to the target file to analyze coverage. */ class CoverageRunner( - private val repoRoot: File, - private val scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher - ) { + private val repoRoot: File, + private val scriptBgDispatcher: ScriptBackgroundCoroutineDispatcher +) { /** * Runs coverage analysis asynchronously for the Bazel test target. @@ -50,10 +49,10 @@ class CoverageRunner( fun getCoverage( bazelTestTarget: String ): List { - val commandExecutor: CommandExecutor = CommandExecutorImpl(scriptBgDispatcher) - val bazelClient = BazelClient(repoRoot, commandExecutor) - val coverageData = bazelClient.runCoverageForTestTarget(bazelTestTarget) - return coverageData + val commandExecutor: CommandExecutor = CommandExecutorImpl(scriptBgDispatcher) + val bazelClient = BazelClient(repoRoot, commandExecutor) + val coverageData = bazelClient.runCoverageForTestTarget(bazelTestTarget) + return coverageData } /** @@ -62,7 +61,7 @@ class CoverageRunner( * @param data the result from the execution of the coverage command * @return the extracted path of the coverage data file. */ - fun parseCoverageDataFile(data: List) : String? { + fun parseCoverageDataFile(data: List): String? { val regex = ".*coverage\\.dat$".toRegex() for (line in data) { val match = regex.find(line) diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt index 07477fa1a48..9ddf3a04450 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt +++ b/scripts/src/java/org/oppia/android/scripts/coverage/RunCoverageForTestTarget.kt @@ -1,8 +1,7 @@ package org.oppia.android.scripts.coverage -import org.oppia.android.scripts.coverage.CoverageRunner -import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher import kotlinx.coroutines.runBlocking +import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher import java.io.File /** @@ -31,7 +30,7 @@ fun main(vararg args: String) { */ class RunCoverageForTestTarget( private val repoRoot: File, - private val targetPath : String + private val targetPath: String ) { /** diff --git a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt index 14ceac6ed9c..30fde89364d 100644 --- a/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt +++ b/scripts/src/java/org/oppia/android/scripts/testing/TestBazelWorkspace.kt @@ -50,6 +50,15 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { assertThat(bazelRcFile.exists()).isTrue() } + /** + * Adds a source file and test file with the specified name and content, + * and updates the corresponding build configuration. + * + * @param filename the name of the source file (without the .kt extension) + * @param sourceContent the content of the source file + * @param testContent the content of the test file + * @param subpackage the subpackage under which the source and test files should be added + */ fun addSourceAndTestFileWithContent( filename: String, sourceContent: String, @@ -90,7 +99,9 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { } // Create the source file - val sourceFile = temporaryRootFolder.newFile("${sourceSubpackage.replace(".", "/")}/$filename.kt") + val sourceFile = temporaryRootFolder.newFile( + "${sourceSubpackage.replace(".", "/")}/$filename.kt" + ) sourceFile.writeText(sourceContent) // Create or update the BUILD file for the source file @@ -106,7 +117,7 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { kt_jvm_library( name = "${filename.lowercase()}", - srcs = ["${filename}.kt"], + srcs = ["$filename.kt"], visibility = ["//visibility:public"], deps = [], ) @@ -154,13 +165,13 @@ class TestBazelWorkspace(private val temporaryRootFolder: TemporaryFolder) { kt_jvm_test( name = "test", - srcs = ["${testName}.kt"], + srcs = ["$testName.kt"], deps = [ "//coverage/main/java/com/example:${filename.lowercase()}", "@maven//:junit_junit", ], visibility = ["//visibility:public"], - test_class = "com.example.${testName}", + test_class = "com.example.$testName", ) """.trimIndent() + "\n" ) diff --git a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt index a6560782a06..9740c1acc3d 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/common/BazelClientTest.kt @@ -16,12 +16,6 @@ import org.oppia.android.testing.mockito.anyOrNull import java.io.File import java.util.concurrent.TimeUnit - - - - - - /** * Tests for [BazelClient]. * @@ -390,39 +384,41 @@ class BazelClientTest { val bazelClient = BazelClient(tempFolder.root, commandExecutor) testBazelWorkspace.initEmptyWorkspace() - val sourceContent = """ - package com.example - - class TwoSum { - - companion object { - fun sumNumbers(a: Int, b: Int): Any { - return if (a ==0 && b == 0) { - "Both numbers are zero" - } else { - a + b - } - } - } - } - """.trimIndent() - - val testContent = """ - package com.example - - import org.junit.Assert.assertEquals - import org.junit.Test - - class TwoSumTest { - - @Test - fun testSumNumbers() { - assertEquals(TwoSum.sumNumbers(0, 1), 1) - assertEquals(TwoSum.sumNumbers(3, 4), 7) - assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") - } - } - """.trimIndent() + val sourceContent = + """ + package com.example + + class TwoSum { + + companion object { + fun sumNumbers(a: Int, b: Int): Any { + return if (a == 0 && b == 0) { + "Both numbers are zero" + } else { + a + b + } + } + } + } + """.trimIndent() + + val testContent = + """ + package com.example + + import org.junit.Assert.assertEquals + import org.junit.Test + + class TwoSumTest { + + @Test + fun testSumNumbers() { + assertEquals(TwoSum.sumNumbers(0, 1), 1) + assertEquals(TwoSum.sumNumbers(3, 4), 7) + assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") + } + } + """.trimIndent() testBazelWorkspace.addSourceAndTestFileWithContent( filename = "TwoSum", diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt index 083fb870bd4..7d3ced9b557 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/CoverageRunnerTest.kt @@ -7,10 +7,8 @@ import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher -import org.oppia.android.testing.assertThrows import org.oppia.android.scripts.testing.TestBazelWorkspace -import kotlin.test.assertEquals -import java.io.File +import org.oppia.android.testing.assertThrows /** Tests for [CoverageRunner] */ class CoverageRunnerTest { @@ -52,7 +50,8 @@ class CoverageRunnerTest { "/path/.cache/bazel/4654367352564/sandbox/__main__/__tmp/coverage/package/test/coverage.dat", "Executed 1 out of 1 test: 1 test passes." ) - val expectedResultParsedData = "/path/.cache/bazel/4654367352564/sandbox/__main__/__tmp/coverage/package/test/coverage.dat" + val expectedResultParsedData = + "/path/.cache/bazel/4654367352564/sandbox/__main__/__tmp/coverage/package/test/coverage.dat" val parsedData = coverageRunner.parseCoverageDataFile(validResultData) assertThat(parsedData).isEqualTo(expectedResultParsedData) @@ -83,39 +82,41 @@ class CoverageRunnerTest { fun testRunCoverage_validSampleTestTarget_returnsCoverageData() { testBazelWorkspace.initEmptyWorkspace() - val sourceContent = """ - package com.example - - class TwoSum { - - companion object { - fun sumNumbers(a: Int, b: Int): Any { - return if (a ==0 && b == 0) { - "Both numbers are zero" - } else { - a + b - } - } - } - } - """.trimIndent() - - val testContent = """ - package com.example - - import org.junit.Assert.assertEquals - import org.junit.Test - - class TwoSumTest { - - @Test - fun testSumNumbers() { - assertEquals(TwoSum.sumNumbers(0, 1), 1) - assertEquals(TwoSum.sumNumbers(3, 4), 7) - assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") - } - } - """.trimIndent() + val sourceContent = + """ + package com.example + + class TwoSum { + + companion object { + fun sumNumbers(a: Int, b: Int): Any { + return if (a ==0 && b == 0) { + "Both numbers are zero" + } else { + a + b + } + } + } + } + """.trimIndent() + + val testContent = + """ + package com.example + + import org.junit.Assert.assertEquals + import org.junit.Test + + class TwoSumTest { + + @Test + fun testSumNumbers() { + assertEquals(TwoSum.sumNumbers(0, 1), 1) + assertEquals(TwoSum.sumNumbers(3, 4), 7) + assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") + } + } + """.trimIndent() testBazelWorkspace.addSourceAndTestFileWithContent( filename = "TwoSum", diff --git a/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt b/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt index 9c28fd9a4b2..2c1d579168f 100644 --- a/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt +++ b/scripts/src/javatests/org/oppia/android/scripts/coverage/RunCoverageForTestTargetTest.kt @@ -61,39 +61,41 @@ class RunCoverageForTestTargetTest { fun testRunCoverageForTestTarget_validSampleTestTarget_returnsCoverageDataPath() { testBazelWorkspace.initEmptyWorkspace() - val sourceContent = """ - package com.example - - class TwoSum { - - companion object { - fun sumNumbers(a: Int, b: Int): Any { - return if (a ==0 && b == 0) { - "Both numbers are zero" - } else { - a + b - } - } - } - } - """.trimIndent() - - val testContent = """ - package com.example - - import org.junit.Assert.assertEquals - import org.junit.Test - - class TwoSumTest { - - @Test - fun testSumNumbers() { - assertEquals(TwoSum.sumNumbers(0, 1), 1) - assertEquals(TwoSum.sumNumbers(3, 4), 7) - assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") - } - } - """.trimIndent() + val sourceContent = + """ + package com.example + + class TwoSum { + + companion object { + fun sumNumbers(a: Int, b: Int): Any { + return if (a ==0 && b == 0) { + "Both numbers are zero" + } else { + a + b + } + } + } + } + """.trimIndent() + + val testContent = + """ + package com.example + + import org.junit.Assert.assertEquals + import org.junit.Test + + class TwoSumTest { + + @Test + fun testSumNumbers() { + assertEquals(TwoSum.sumNumbers(0, 1), 1) + assertEquals(TwoSum.sumNumbers(3, 4), 7) + assertEquals(TwoSum.sumNumbers(0, 0), "Both numbers are zero") + } + } + """.trimIndent() testBazelWorkspace.addSourceAndTestFileWithContent( filename = "TwoSum", @@ -111,4 +113,4 @@ class RunCoverageForTestTargetTest { val parsedCoverageDataPath = result?.endsWith("coverage.dat") assert(parsedCoverageDataPath!!) { "The coverage.dat is not generated" } } -} \ No newline at end of file +} From 49d6dbbf2d5d4f007310927fc14a6b2e348cc64a Mon Sep 17 00:00:00 2001 From: Rd Date: Thu, 13 Jun 2024 11:31:27 +0530 Subject: [PATCH 12/12] Fix Buildifier Lint checks --- .../src/java/org/oppia/android/scripts/coverage/BUILD.bazel | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel index 924011c5225..53f09dbb98c 100644 --- a/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel +++ b/scripts/src/java/org/oppia/android/scripts/coverage/BUILD.bazel @@ -1,3 +1,7 @@ +""" +Libraries corresponding to developer scripts that obtain coverage data for test targets. +""" + load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library") kt_jvm_library( @@ -8,9 +12,9 @@ kt_jvm_library( ], visibility = ["//scripts:oppia_script_binary_visibility"], deps = [ - "//scripts/src/java/org/oppia/android/scripts/coverage:coverage_runner", "//scripts/src/java/org/oppia/android/scripts/common:bazel_client", "//scripts/src/java/org/oppia/android/scripts/common:git_client", + "//scripts/src/java/org/oppia/android/scripts/coverage:coverage_runner", ], )