We use JUnit as a test framework. We have many projects. We use gradle (version 1.12) as a build tool. To run the unit tests in parallel using gradle we use the below script in every project under test task.
maxParallelForks = Runtime.runtime.availableProcessors()
Ex:
test {
maxParallelForks = Runtime.runtime.availableProcessors()
}
We also maintain the single gradle.properties file.
Is it possible to define test.maxParallelForks = Runtime.runtime.availableProcessors() in gradle.properties file rather than defining it in each build.gradle file under test task?
The accepted answer above works but the Gradle documentation here suggests you use
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
I tried both and after testing both on a 2.3 GHz Intel Core i7 Mac Book Pro with 16GB RAM (4 cores with hyperthreading)
test {
maxParallelForks = Runtime.runtime.availableProcessors()
}
and
test {
maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1
}
The approach suggested by Gradle documentation produced faster response times for our unit test suite: 7 minutes vs. 8 minutes (compared to the original 13 minutes). In addition my Mac CPU didn't get pegged and the fan didn't kick off.
I assume there is either contention on a shared resource - even if it is only the machine one which we are running the unit tests.
$rootDir/build.gradle:
subprojects {
tasks.withType(Test) {
maxParallelForks = Runtime.runtime.availableProcessors()
}
}
For those of us using Gradle Kotlin DSL in a build.gralde.kts who find themselves here after a google search, I was able to get it to work this way:
tasks.test {
maxParallelForks = Runtime.getRuntime().availableProcessors()
}
or
tasks.withType<Test> {
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
}
as I found here
edit: I ran into some issue as described here. This is (hopefully) my final form:
tasks.withType<Test> {
systemProperties["junit.jupiter.execution.parallel.enabled"] = true
systemProperties["junit.jupiter.execution.parallel.mode.default"] = "concurrent"
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
}
kotlin gradle dsl
tasks.withType<Test> {
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1).also {
println("Setting maxParallelForks to $it")
}
}
Related
I want to modify my build.gradle.kts by implementing some tasks. Specially, I want to obtain the output of the first task in my second task, where the first task runs a shell command. There are some basic examples here and here, which are implemented in groovy dsl. Now, I need this functionality in kotlin dsl.
A working example is:
task<Exec>("avdIsRunning") {
commandLine("adb", "devices")
standardOutput = ByteArrayOutputStream()
}
task("task2") {
dependsOn("avdIsRunning")
doLast {
val standardOutput = (tasks.getByName("avdIsRunning") as Exec).standardOutput.toString()
println("Foo's output: $standardOutput")
}
}
What I want is, to call a extension method avdIsRunning.output() that provides the standradOutput of avdIsRunning-task, compare to the examples I linked above.
I have a class that runs various test suites. Every subsequent test suite fails because the app state isn't cleared between test suites. I do not want to use Android Orchestrator because that clears data between every test, I only want to do it between suites.
I have some code already which may clear data but no tests run after it is called so I'm at a loss currently.
#RunWith(Categories::class)
#Categories.IncludeCategory(RegressionTests::class)
#Suite.SuiteClasses( AuthenticationTests::class,
AuthenticationInvalidTests::class,
CreateAccountTests::class,
AccountSecurityTests::class,
CountrySelectionTests::class
)
// Run this class to run regression tests
class RegressionTests {
// Clear app data between test suites
companion object {
#ClassRule
#JvmField
val resource: ExternalResource = object : ExternalResource() {
override fun after() {
val context = getApplicationContext<Context>()
val runtime = Runtime.getRuntime()
runtime.exec("pm clear ${context.packageName}")
}
}
}
}
I have a ChiselTest tester written as follows:
class EccTester extends FlatSpec with ChiselScalatestTester with Matchers {
behavior of "Testers2"
it should "send data without errors" in {
test(new EccPair(width=8)) {
c => {
val rnd = new Random()
for (i <- 0 to 20) {
val testVal = rnd.nextInt(1 << c.getWidthParam)
c.io.dataIn.poke(testVal.U)
c.io.errorLocation.poke(0.U)
c.io.injectError.poke(false.B)
c.io.injectSecondError.poke(false.B)
c.clock.step(1)
c.io.dataOut.expect(testVal.U)
c.io.outputNotEqual.expect(false.B)
}
}
}
}
}
I am able to run the test in the shell with
testOnly chisel.lib.ecc.EccTester
But when I try to generate waveforms per the ChiselTest documentation,
testOnly chisel.lib.ecc.EccTester -- -DvwriteVcd=1
The test executes OK but does not dump a waveform.
Documentation I referenced is https://github.com/ucb-bar/chisel-testers2, and the full source code is at https://github.com/hutch31/ip-contributions/blob/ecc/src/test/scala/chisel/lib/ecc/EccTester.scala
I don’t think there is a formal answer to this yet, but here’s what I do. First I add the two following imports.
import chiseltest.experimental.TestOptionBuilder._
import chiseltest.internal.WriteVcdAnnotation
then add the annotation to the test like this
it should "send data without errors" in {
test(new EccPair(width=8)).withAnnotations(Seq(WriteVcdAnnotation)) {
c => {
Note: there are two definitions of WriteVcdAnnotation, one is in package treadle
and the other is in package chiseltest.internal. Use the latter, as it will work
for both treadle and verilator backends.
I've created a method, and the return is Result<R> in a class of MyClass<R>, but the error message is: 'kotlin.Result' cannot be used as a return type
I've also looked into the Result source code for some hints; why is this so?
Test code (using v. 1.3-RC).
class MyClass<R>(val r: R) {
fun f(): Result<R> { // error here
return Result.success(r)
}
}
fun main(args: Array<String>) {
val s = Result.success(1)
val m = MyClass(s)
}
From the Kotlin KEEP:
The rationale behind these limitations is that future versions of
Kotlin may expand and/or change semantics of functions that return
Result type and null-safety operators may change their semantics when
used on values of Result type. In order to avoid breaking existing
code in the future releases of Kotin and leave door open for those
changes, the corresponding uses produce an error now. Exceptions to
this rule are made for carefully-reviewed declarations in the standard
library that are part of the Result type API itself.
Note: if you just want to experiment with the Result type you can bypass this limitation by supplying a Kotlin compiler argument -Xallow-result-return-type.
When using Gradle on Java or Android project:
Define the compiler argument on Kotlin compilation task. It applies both for production code and tests.
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + "-Xallow-result-return-type"
}
}
When using Gradle on Multiplatform project:
Define the compiler argument for each target compilation. It applies both for production code and tests.
kotlin {
targets.all {
compilations.all {
kotlinOptions {
freeCompilerArgs = freeCompilerArgs + "-Xallow-result-return-type"
}
}
}
}
android {
kotlinOptions {
freeCompilerArgs = ["-Xallow-result-return-type"]
}
}
If you using android this solution for gradle
If using maven:
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<configuration>
<jvmTarget>1.8</jvmTarget>
<args>
<arg>-Xallow-result-return-type</arg>
</args>
</configuration>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
If using gradle:
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.freeCompilerArgs = ["-Xallow-result-return-type"]
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.freeCompilerArgs = ["-Xallow-result-return-type"]
}
Source: http://rustyrazorblade.com/post/2018/2018-12-06-kotlin-result/
Update the kotlin version to 1.5 or above. See:
https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/result.md#limitations-legacy
I've got a mixed Java / Scala project with both JUnit and ScalaTest tests. With the scalatest plugin, Gradle runs the ScalaTest tests in src/test/scala, but ignores the JUnit tests in src/test/java. Without the plugin, Gradle runs the JUnit tests but ignores the Scala. What trick am I missing?
My build.gradle:
plugins {
id 'java'
id 'maven'
id 'scala'
id "com.github.maiflai.scalatest" version "0.6-5-g9065d91"
}
sourceCompatibility = 1.8
group = 'org.chrononaut'
version = '1.0-SNAPSHOT'
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
ext {
scalaMajorVersion = '2.11'
scalaVersion = "${scalaMajorVersion}.5"
}
repositories {
mavenCentral()
mavenLocal()
}
dependencies {
compile "org.scala-lang:scala-library:${scalaVersion}"
compile "org.scala-lang.modules:scala-xml_${scalaMajorVersion}:1.0.3"
compile 'com.google.guava:guava:18.0'
compile 'javax.xml.bind:jaxb-api:2.2.12'
compile 'jaxen:jaxen:1.1.6'
compile 'joda-time:joda-time:2.7'
compile 'org.joda:joda-convert:1.7'
compile 'org.apache.commons:commons-lang3:3.3.2'
compile 'org.jdom:jdom2:2.0.5'
testCompile 'junit:junit:4.12'
testCompile 'org.easytesting:fest-assert:1.4'
testCompile 'org.mockito:mockito-core:1.10.19'
testCompile "org.scalatest:scalatest_${scalaMajorVersion}:2.2.4"
testRuntime 'org.pegdown:pegdown:1.1.0' // required by scalatest plugin
}
compileScala {
scalaCompileOptions.additionalParameters = [
"-feature",
"-language:reflectiveCalls", // used for config structural typing
"-language:postfixOps"
]
}
ETA: I know it's possible to annotate Scala tests to force them to run with the JUnit test runner. I'm looking for a one-stop build.gradle solution that doesn't require editing every test file (or messing with the tests to get around limitations in the build system, in general).
Another alternative to running with JUnit (and to creating an Ant task as suggested in comments) - is creating a task that runs ScalaTest's Runner directly:
task scalaTest(dependsOn: ['testClasses'], type: JavaExec) {
main = 'org.scalatest.tools.Runner'
args = ['-R', 'build/classes/test', '-o']
classpath = sourceSets.test.runtimeClasspath
}
test.dependsOn scalaTest // so that running "test" would run this first, then the JUnit tests
Get rid of the plugin, as it makes test task to run ScalaTest only (so JUnit gets ignored).
Annotate your ScalaTests with #RunWith(classOf[JUnitRunner])so they can be run by gradle as JUnit tests.
With the latest version of scala-test plugin you can choose whether the existing (junit)-test task is replaced or not by the scala-tests-task. In your case you could use the following in
gradle.properties:
com.github.maiflai.gradle-scalatest.mode = append
Now you can execute both tests:
junit: gradle test
scala-test: gradle scalatest
or combine them into one task
task allTests {
dependsOn test
dependsOn scalatest
}
That worked for me.
There is an easier solution these days.
You can just specify multiple junit test engines in useJUnitPlatform using scalatest-junit-runner for scala:
dependencies {
// junit platform
testRuntimeOnly("org.junit.platform:junit-platform-engine")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// junit5 engine
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
// junit4 engine
testRuntimeOnly("org.junit.vintage:junit-vintage-engine")
// scalatest engine
testRuntimeOnly("co.helmethair:scalatest-junit-runner")
}
test {
useJUnitPlatform {
includeEngines "junit-jupiter", "junit-vintage", "scalatest"
testLogging {
events("passed", "skipped", "failed")
}
}
}
You can even implement your own similar to ScalatestEngine this library provides.
One more useful link https://github.com/junit-team/junit5-samples/blob/main/junit5-migration-gradle/README.md