29
task scalaTest(dependsOn: testClasses) << {
    description = 'Runs Scalatest suite'
    ant.taskdef(name: 'scalatest',
            classname: 'org.scalatest.tools.ScalaTestAntTask',
            classpath: sourceSets.test.runtimeClasspath.asPath
    )
    ant.scalatest(runpath: sourceSets.test.output.classesDir,
            haltonfailure: 'true', fork: 'false') {
        reporter(type: 'stdout')
    }
}

I run gradle scalaTest and I get:

* What went wrong:
Execution failed for task ':scalaTest'.
> java.lang.NoClassDefFoundError: scala/reflect/ClassManifest$

I am using Scala 2.10.2 and Gradle 1.7

dependencies {
    compile 'org.scala-lang:scala-library:2.10.2'   
    testCompile 'org.scalatest:scalatest:1.3'
    testCompile 'org.scalamock:scalamock_2.10:3.0.1'
}

What's wrong??

Joshua MN
  • 1,486
  • 2
  • 13
  • 26

5 Answers5

34

I do not know how to solve this one, but I can offer you a workaround. Annotate your test classes with @RunWith(classOf[JUnitRunner]), like this:

import org.scalatest.junit.JUnitRunner
import org.junit.runner.RunWith

@RunWith(classOf[JUnitRunner])
class MyTest extends FunSpec{
}

and then, gradle test should work.

Edit:

My dependencies:

compile "org.scala-lang:scala-library:2.10.1"
testCompile "org.scalatest:scalatest_2.10:1.9.1"
rarry
  • 3,553
  • 20
  • 23
  • The behavior is different, but still doesnt work: *initializationError java.lang.NoClassDefFoundError: scala/reflect/ClassManifest* in the report's index.html – Joshua MN Sep 16 '13 at 09:16
  • 8
    I think that the scalatest dependency should be testCompile instead of compile. – Eric Pabst Feb 06 '14 at 06:25
24

You can put the following in your build.gradle:

task spec(dependsOn: ['testClasses'], type: JavaExec) {
  main = 'org.scalatest.tools.Runner'
  args = ['-R', 'build/classes/scala/test', '-o']
  classpath = sourceSets.test.runtimeClasspath
}

Note: The path my be different depending on the gradle version as pointed out in the comments by @MikeRylander. Before gradle 4 it used to be 'build/classes/test'.

Then just run gradle spec to execute your tests. I named the task spec because there already is a test task. I don't know if you can override the default test task.

You can look up the available options here.

peterh
  • 11,875
  • 18
  • 85
  • 108
Machisuji
  • 738
  • 7
  • 16
5

This response may be a bit late. But for one using scala with gradle (5.x), the following works.

Add the following plugin to gradle.

plugins {
  id "com.github.maiflai.scalatest" version "0.25"
}

To run the code

> gradle test

As a bonus the test results from the above plugin would also be reported better than the default report.

Developer
  • 691
  • 8
  • 7
  • 1
    I also had to add this dependency: `testRuntime 'org.pegdown:pegdown:1.4.2'` – DeegC Sep 21 '19 at 21:50
  • Any reference where this solution is used? With gradle 5.0, I get the following error "No signature of method: static org.gradle.process.internal.DefaultExecActionFactory.root() is applicable for argument types: () values: [] Possible solutions: wait(), stop(), wait(long), print(java.lang.Object), print(java.io.PrintWriter), wait(long, int)" – nashter Apr 05 '20 at 20:27
  • This answered helped me, thanks! Just a heads-up - make sure that the plugin is applied (no `.apply(false)`). In other words, the definition should NOT look like below: `id("com.github.maiflai.scalatest").version("0.25").apply(false)` – Vlad.Bachurin Feb 26 '21 at 11:27
3

rarry is correct. And even better, you can annotate a base test class with @RunWith(classOf[JUnitRunner]) once to cause all of your ScalaTest tests to run with the JUnit runner (assuming they extend the base class), e.g.:

import org.junit.runner.RunWith
import org.scalatest._
import org.scalatest.junit.JUnitRunner

@RunWith(classOf[JUnitRunner])
abstract class UnitSpec extends FlatSpec with Matchers
voxoid
  • 1,164
  • 1
  • 14
  • 31
3

As of Gradle 3.2.1, following root build.gradle runs both JUnit and ScalaTest code. This code is for multi-project build, enabled via settings.gradle, that's why subprojects used.
Plus, it's on purpose uses explicit Gradle API, to minimize Gradle DSL magic.

description = 'root project'

def enableScalaTest(Project project) {
    Task scalaTest = project.task(
            [
                    'dependsOn': 'testClasses',
                    'description': 'Runs ScalaTest tests in the project'
            ],
            'scalaTest',
            {
                ext.inputDir = project.tasks.getByName('compileTestScala').destinationDir
                inputs.dir(ext.inputDir)
            }
    )

    scalaTest.doLast({
        ant.taskdef(name: 'scalatest',
                classname: 'org.scalatest.tools.ScalaTestAntTask',
                classpath: project.sourceSets.test.runtimeClasspath.asPath)
        ant.scalatest(runpath: ext.inputDir,
                fork: 'false',
                haltonfailure: 'true')
                { reporter(type: 'stdout') }
    })

    project.getTasks().getByName('build').dependsOn(scalaTest)
}

subprojects {
    apply plugin: 'scala'

    repositories {
        mavenCentral()
    }

    dependencies {
        compile 'org.scala-lang:scala-library:2.12.1'

        testCompile 'junit:junit:4.12'
        testCompile 'org.scalatest:scalatest_2.12:3.0.1'
    }

    enableScalaTest(delegate)
}
Victor Sorokin
  • 11,878
  • 2
  • 35
  • 51