Maven Integration

365 views
Skip to first unread message

Erik Peterson

unread,
Jul 12, 2011, 11:29:55 PM7/12/11
to scalate...@googlegroups.com
Our deployment system uses continuous build servers in multiple stages--with maven. So if I can demonstrate seamless maven integration I think we can begin using ScalaTest.

Can you point me to a resource that shows how to configure standard maven phases to run FunSuite tests? I'm not seeing all the tests run from command line, but from Intellij they all run. Thanks.

Sean Griffin

unread,
Jul 13, 2011, 12:11:20 AM7/13/11
to scalatest-users
Erik,
I can speak to this one as I do this all the time. I don't know of a
central resource that tells front-to-back how to accomplish it, but
I'll just include it here. There are really only 3 basic steps:
1. Include the maven-scala-plugin in your pom
2. Ensure your test files end with "Test" (or you can configure
Surefire to find your alternatively-named tests)
3. Include the @RunWith(classOf[JUnitRunner]) at the top of your tests

To give more details, I usually have this boilerplate in my POM:

<build>
<sourceDirectory>src/main/scala</sourceDirectory>
<testSourceDirectory>src/test/scala</testSourceDirectory>
...
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>${maven.scala.plugin.version}</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<jvmArgs>
<jvmArg>-Xmx384m</jvmArg>
</jvmArgs>
<args>
<arg>-target:jvm-1.5</arg>
<arg>-deprecation</arg>
</args>
<launchers>
<launcher>
<id>run-scalatest</id>
<mainClass>org.scalatest.tools.Runner</mainClass>
<args>
<arg>-p</arg>
<arg>${project.build.testOutputDirectory}</arg>
</args>
<jvmArgs>
<jvmArg>-Xmx512m</jvmArg>
</jvmArgs>
</launcher>
</launchers>
</configuration>
</plugin>
...

Then, assuming I have a class called "MyFunTest" in a package under
src/test/scala, I'll define my class like:

@RunWith(classOf[JUnitRunner])
class MyFunTest extends FunSuite with MustMatchersForJUnit


That really should be all you need. The additional "launcher"
configuration I included in the plugin definition in the POM allows me
to get the output of ScalaTest's Runner as opposed to the Surefire
output if I so desire (this is expecially important for getting the
BDD output of FeatureSpec, which I do often).

Erik Peterson

unread,
Jul 13, 2011, 1:35:14 AM7/13/11
to scalate...@googlegroups.com
How would this be configured in maven to work with TestNG and functional tests? Do test() functions need to be annotated?

class MyTest extends Assertions with FunSuite {

 @Test def test_CreatePersonExt: Unit = {
    assert(true === false)
  }

test("Value is even") {
    val v = 5
    assert(v % 2 === 0)
  }
}

Bill Venners

unread,
Jul 13, 2011, 2:42:19 AM7/13/11
to scalate...@googlegroups.com
Hi Erik,

First, thanks Sean for such a nice answer about Maven. I will try and
capture that info on the user guide I'm polishing off, so there will
be a central place.

As to your question about TestNG, Erik, what Sean showed you was how
to run any style of ScalaTest suite or spec through Maven. It is done
by going through JUnit, which most tools understand. If you want to
write TestNG tests in Scala, you can do that, and ScalaTest also has
some integration, but those look like and actually are TestNG tests.
Thus you'd make test methods and put the @Test annotation on them.
Here's an example:

http://www.scalatest.org/scaladoc-1.6.1/#org.scalatest.testng.TestNGSuite

A TestNGSuite is both a ScalaTest Suite and a TestNG test class. They
can be run with either ScalaTest or TestNG. Because they actually are
TestNG test classes, you can run them with Maven however you are
running any other TestNG test classes written in Java or any other JVM
language. But if you want to do FunSuites or FeatureSpecs, etc., you'd
put on JUnitRunner and let Maven those run through JUnit.

Bill

> --
> You received this message because you are subscribed to the Google
> Groups "scalatest-users" group.
> To post to this group, send email to scalate...@googlegroups.com
> To unsubscribe from this group, send email to
> scalatest-use...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/scalatest-users?hl=en
> ScalaTest itself, and documentation, is available here:
> http://www.artima.com/scalatest

--
Bill Venners
Artima, Inc.
http://www.artima.com

Erik Peterson

unread,
Jul 13, 2011, 7:19:56 PM7/13/11
to scalate...@googlegroups.com
Thank you gentlemen for your assistance. I'm still unable to get mvn and FunSuite working together. Here are my results with 3 cases.

1) Apparently Mixing TestNG and FunSuite is not supported, correct?

@RunWith(classOf[JUnitRunner])
class FunRunTest extends TestNGSuite with FunSuite {
 @Test def canaryTest: Unit = assert(true === true)
 test("Value is even") { assert(4 % 2 === 0)}
}

error: overriding method runTest in trait TestNGSuite of type (testName: String, reporter: org.scalatest.Reporter, stopper: org.scalatest.Stopper, configMap: Map[String,Any], tracker: org.scalatest.Tracker)Unit; .......

2) The following works in intellij and from maven cli (mvn -Dtest=FunRunTest clean test):

class FunRunTest extends TestNGSuite {
 @Test def canaryTest: Unit = assert(true === true)
}

3) The following works in intellij, but FAILS from maven cli (mvn -Dtest=FunRunTest clean test):

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:2.7.2:test (default-test) on project simple: No tests were executed!  (Set -DfailIfNoTests=false to ignore this error.) -> [Help 1]

//note that adding or removing this annotation has no impact on the test result, just doesn't find the test
@RunWith(classOf[JUnitRunner])
class FunRunTest extends FunSuite {
 test("Value is even") { assert(4 % 2 === 0)}
}

Note that I don't specify sourceDirectory or testSourceDirectory. This is a mixed project with scala and java and maven allows defining only one instance of each. But the Scala compiler handles compiling all *.scala and *.java files, so this hasn't been an issue so far.

pom.xml section...

 <build>

    <plugins>
      <plugin>
        <groupId>org.scala-tools</groupId>
        <artifactId>maven-scala-plugin</artifactId>
        <version>2.14.1</version>

        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
              <goal>testCompile</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <scalaVersion>${scalaVersion}</scalaVersion>

          <launchers>
            <launcher>
             <id>run-scalatest</id>
             <mainClass>org.scalatest.tools.Runner</mainClass>
             <args>
               <arg>-p</arg>
               <arg>${project.build.testOutputDirectory}</arg>
             </args>
             <jvmArgs>
               <jvmArg>-Xmx512m</jvmArg>
             </jvmArgs>
           </launcher>
          </launchers>
          <jvmArgs>
            <jvmArg>-Xms64m</jvmArg>
            <jvmArg>-Xmx1024m</jvmArg>
          </jvmArgs>
        </configuration>
      </plugin>
      <plugin>
       <groupId>org.apache.maven.plugins</groupId>
       <artifactId>maven-jar-plugin</artifactId>
       <version>2.2</version>
       <executions>
         <execution>
           <goals>
             <goal>test-jar</goal>
           </goals>
         </execution>
       </executions>
     </plugin>
    </plugins>
  </build>








Bill Venners

unread,
Jul 13, 2011, 7:28:54 PM7/13/11
to scalate...@googlegroups.com
Hi Erik,

On Wed, Jul 13, 2011 at 4:19 PM, Erik Peterson <coach...@gmail.com> wrote:
> Thank you gentlemen for your assistance. I'm still unable to get mvn and
> FunSuite working together. Here are my results with 3 cases.
>
> 1) Apparently Mixing TestNG and FunSuite is not supported, correct?
>
> @RunWith(classOf[JUnitRunner])
> class FunRunTest extends TestNGSuite with FunSuite {
>  @Test def canaryTest: Unit = assert(true === true)
>  test("Value is even") { assert(4 % 2 === 0)}
> }
>
> error: overriding method runTest in trait TestNGSuite of type (testName:
> String, reporter: org.scalatest.Reporter, stopper: org.scalatest.Stopper,
> configMap: Map[String,Any], tracker: org.scalatest.Tracker)Unit; .......
>

Correct. Those two aren't designed to stack, so they don't compile
when you attempt that. Reason is that TestNGSuite is also a TestNG
test class, and TestNG would have no idea what to do with test("...")
{ ... }.

> 2) The following works in intellij and from maven cli (mvn -Dtest=FunRunTest
> clean test):
>
> class FunRunTest extends TestNGSuite {
>  @Test def canaryTest: Unit = assert(true === true)
> }
>

Yes, that's just using TestNGSuite.

> 3) The following works in intellij, but FAILS from maven cli (mvn
> -Dtest=FunRunTest clean test):
>
> [ERROR] Failed to execute goal
> org.apache.maven.plugins:maven-surefire-plugin:2.7.2:test (default-test) on
> project simple: No tests were executed!  (Set -DfailIfNoTests=false to
> ignore this error.) -> [Help 1]
>
> //note that adding or removing this annotation has no impact on the test
> result, just doesn't find the test
> @RunWith(classOf[JUnitRunner])
> class FunRunTest extends FunSuite {
>  test("Value is even") { assert(4 % 2 === 0)}
> }
>
> Note that I don't specify sourceDirectory or testSourceDirectory. This is a
> mixed project with scala and java and maven allows defining only one
> instance of each. But the Scala compiler handles compiling all *.scala and
> *.java files, so this hasn't been an issue so far.
>

Hmm. Code looks fine so maybe this is the issue. Somehow Maven needs
to discover your class. It does by default look for classes ending
with "Test" like you have. So it is probably that it isn't looking in
the correct directory. Does maven actually look for source files with
that name? Because I'd have figured they'd be rooting through the
class files.

Bill

Sean Griffin

unread,
Jul 13, 2011, 11:14:22 PM7/13/11
to scalatest-users
Well, there are a couple potential problems. First, in my experience,
Surefire doesn't like JUnit and TestNG on the classpath at the same
time. You either use TestNG *or* JUnit but as soon as you put both
JARs on the classpath then it'll pick one (TestNG, I think, but that
may have just been the order it loaded the classes) and attempt to
register the classes it finds with that one testing framework. This
may have been addressed in a more recent version of Surefire; I was
testing with 2.5 or somewhere around there.

Second, and more important, IntelliJ might be smart enough to find
both source directories, and the Scala compiler is smart enough to
compile both Java and Scala source files, but Maven cannot, like you
say, have more than one source directory...by default, that is. If
that's really what you have then you need to pull in the Build Helper
Maven Plugin and configure its add-source or add-test-source goals.

So one setup might be Java source with Scala tests. In this case it's
simple. You just add "<testSourceDirectory>src/test/scala</
testSourceDirectory>" to your <build> section and you're good. If,
however, you have tests in both src/test/java and src/test/scala then
you'll have to select your "primary" testSourceDirectory and add the
other directory through the build helper plugin.

Erik Peterson

unread,
Jul 14, 2011, 11:32:09 AM7/14/11
to scalate...@googlegroups.com
I've tried variations using JUnit and Build Helper Maven Plugin. But still no success getting FunRunTest to execute from Maven. I've attached a sample project to demonstrate the problem. Would love to have this working for training this afternoon. But I'm stuck. So thank you for your assistance. -Erik
simple-testing-scalatest.zip

Erik Peterson

unread,
Jul 14, 2011, 5:37:05 PM7/14/11
to scalate...@googlegroups.com
Just to follow up that the training on ScalaTest went well except for this issue. Would really like to get this resolved before the next training. The use case is to add ScalaTest and its FunSuite trait to existing Java/maven projects. Seems that this would be a fairly common use case as existing Java shops evaluate Scala. Thanks again!

Sean Griffin

unread,
Jul 14, 2011, 11:48:46 PM7/14/11
to scalate...@googlegroups.com
I downloaded your project and tried it out.  You're getting this behavior because of the issue I mentioned previously about JUnit and TestNG in use at the same time. Surefire apparently still doesn't like that combination and once it sees TestNG stuff it ignores anything set to run under JUnit.  Since your FunSuite will use the JUnitRunner Surefire is simply ignoring it.  To prove it out, I removed testng from the POM and removed the tests that rely on TestNG and sure enough your FunRunTest runs and passes at that point.

On Thu, Jul 14, 2011 at 4:37 PM, Erik Peterson <coach...@gmail.com> wrote:
Just to follow up that the training on ScalaTest went well except for this issue. Would really like to get this resolved before the next training. The use case is to add ScalaTest and its FunSuite trait to existing Java/maven projects. Seems that this would be a fairly common use case as existing Java shops evaluate Scala. Thanks again!

Sean Griffin

unread,
Jul 14, 2011, 11:58:38 PM7/14/11
to scalate...@googlegroups.com
One more thing...  I just did a little brief research and ran across this possible solution if you really need to have JUnit and TestNG in use at the same time.  Hope it helps: http://confluence.highsource.org/display/~lexi/How+to+run+both+JUnit+and+TestNG+with+maven-surefire-plugin

Erik Peterson

unread,
Jul 15, 2011, 1:56:39 PM7/15/11
to scalate...@googlegroups.com
Sean,
That's it! You found the secret sauce. Thank you!

I've attached an updated sample project with Java and Scala source that uses Maven, TestNG, and ScalaTest (with FunSuite test functions).

Hope this helps others evaluating Scala and ScalaTest with existing Java/Maven projects. Very easy to roll in Scala without changing existing JVM deployment infrastructure.
Erik
simple-testing-scalatest.zip

Bill Venners

unread,
Jul 15, 2011, 2:23:50 PM7/15/11
to scalate...@googlegroups.com
Hi Erik and Sean,

Thanks so much, Sean, for all your helpful answers. I'm at the
Scalathon documentation day right now, and will be working on the user
guide today. I'll try and get this in there so it is in a central
place.

Bill

> --
> You received this message because you are subscribed to the Google
> Groups "scalatest-users" group.
> To post to this group, send email to scalate...@googlegroups.com
> To unsubscribe from this group, send email to
> scalatest-use...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/scalatest-users?hl=en
> ScalaTest itself, and documentation, is available here:
> http://www.artima.com/scalatest

--

Reply all
Reply to author
Forward
0 new messages