使用 ScalaTest 将附加参数传递给测试

Passing additional arguments to tests with ScalaTest

目前我正在使用 IntelliJ Idea 15 和 Scalatest 框架进行一些单元测试。我需要将自己的参数传递给测试并以某种方式从代码中读取它们。例如: 假设我有这样的class

class Test extends FunSuite {
   test("Some test") {
       val arg = // here I want to get an argument which I want to pass. Something like args("arg_name")
       println(arg)
       assert(2 == 2)
   }
}

对于 运行 带有参数的测试,我想做类似

的事情
test -arg_name=blabla

所以,问题是如何传递这个参数以及如何获取它。

scalatest中,我们可以使用configMap来传递命令参数。

有一个使用 configMap 的例子:

import org.scalatest.{ConfigMap, fixture}

class TestSuite extends fixture.Suite with fixture.ConfigMapFixture{
  def testConfigMap(configMap: Map[String, Any]) {
    println(configMap.get("foo"))
    assert(configMap.get("foo").isDefined)
  }
}

object Test {
  def main(args: Array[String]): Unit = {
    (new TestSuite).execute(configMap = ConfigMap.apply(("foo","bar")))
  }
}

我们也可以运行使用命令行参数进行测试:

scala -classpath scalatest-<version>.jar org.scalatest.tools.Runner -R compiled_tests -Dfoo=bar

scalatest runner ConfigMapFixture Test

我发现了有趣的特性 BeforeAndAfterAllConfigMap。这个有 beforeAll 方法,参数是 configMap:ConfigMap。所以这是我的解决方案:

class Test extends FunSuite with BeforeAndAfterAllConfigMap {

  override def beforeAll(configMap: ConfigMap) = {
    //here will be some stuff and all args are available in configMap
  }

  test("Some test") {
    val arg = // here I want to get an argument which I want to pass. Something like args("arg_name")
    println(arg)
    assert(2 == 2)
  }
}

我发现 BeforeAndAfterAllConfigMap 如果您已经在使用 FunSpec、FunSuite 或 FlatSpec,则可以轻松地合并到现有的 scalatest 中。您所要做的就是使用 BeforeAndAfterAllConfigMap.

导入和扩展您的测试

您可以将参数传递给 scalatest 的方法之一是:

  1. 从命令行传递参数 系统或项目 属性
  2. 在 build.gradle 文件中检索 [系统|项目] 属性
  3. 将第2步中检索到的属性传给 测试运行时。

这是 FlatSpec 中的一个完整示例,但也很容易适用于 FunSuite:

package com.passarg.test
import org.scalatest.{BeforeAndAfterAllConfigMap, ConfigMap, FlatSpec}

class PassArgsToScala extends FlatSpec with BeforeAndAfterAllConfigMap { 

  var foo = ""

  override def beforeAll(configMap: ConfigMap) = {
      // foo=bar is expected to be passed as argument
      if (configMap.get("foo").isDefined) {
          foo = configMap.get("foo").fold("")(_.toString)
      }
      println("foo=" + foo)
  }

  "Arg passed" must "be bar" in {
      assert(foo === "bar")
      info("passing arg seem to work ==> " + "foo=" + foo)
  }
}

build.gradle

apply plugin: 'scala'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.scala-lang:scala-library:2.11.8'
    testCompile 'org.scalatest:scalatest_2.11:3.0.0'
}

task spec(dependsOn: ['testClasses']) {
    javaexec {
        main = 'org.scalatest.tools.Runner'
        args = ['-R', 'build/classes/test', '-o']
        args += '-m'
        args += 'com.passarg.test'
        if (project.hasProperty("foo")) {
            args += "-Dfoo=" + project.foo
        }
        classpath = sourceSets.test.runtimeClasspath
   }
}

运行 来自命令行的测试:

./gradlew -q spec -Pfoo=bar

结果:

$ ./gradlew -q spec -Pfoo=bar
...
Run starting. Expected test count is: 1
PassArgsToScala:
Arg passed
- must be bar
   + passing arg seem to work ==> foo=bar 

我最近不得不将一个功能标志传递给 scalatest 测试,这样我就可以测试相同 API 的两个实现。我为此使用了一个环境变量。它适用于 sbt 和 maven。变量的内容将在 configMap 中结束。如何处理 configMap 你可以查看其他帖子(或在 the post I base this answer on)。

您可以按如下方式传递参数“ABC”:

FEATURE_FLAG="ABC" sbt test
# or 
FEATURE_FLAG="ABC" mvn test

sbt 设置:

// build.sbt
val featureFlagArg = sys.env.get("FEATURE_FLAG")
  .map(ff => s"-DfeatureFlag=$ff")
  .map(Tests.Argument(TestFrameworks.ScalaTest, _))
Test / testOptions ++= featureFlagArg

maven 设置(使用 scalatest maven 插件):

<!-- pom.xml -->
<!-- ... -->
<plugin>
  <groupId>org.scalatest</groupId>
  <artifactId>scalatest-maven-plugin</artifactId>
  <version>1.0</version>
  <configuration>
    <config>featureFlag=${env.FEATURE_FLAG}</config>
  </configuration>
  <executions>
    <execution>
      <id>test</id>
      <goals>
        <goal>test</goal>
      </goals>
    </execution>
  </executions>
</plugin>
<!-- ... -->