【问题标题】:Parallel execution of tests并行执行测试
【发布时间】:2015-01-02 23:27:28
【问题描述】:

我注意到 SBT 正在并行运行我的 specs2 测试。这看起来不错,除了我的一个测试涉及从文件读取和写入,因此无法预测地失败,例如见下文。

还有比这更好的选择

  1. 将所有测试设置为串行运行,
  2. 为每个测试使用单独的文件名和拆解?
class WriteAndReadSpec extends Specification{
  val file = new File("testFiles/tmp.txt")

  "WriteAndRead" should {
    "work once" in {
      new FileWriter(file, false).append("Foo").close
      Source.fromFile(file).getLines().toList(0) must_== "Foo"
    }
    "work twice" in {
      new FileWriter(file, false).append("Bar").close
      Source.fromFile(file).getLines().toList(0) must_== "Bar"
    }
  }

  trait TearDown extends After {
    def after = if(file.exists) file.delete
  }
}

【问题讨论】:

    标签: scala sbt specs2


    【解决方案1】:

    除了上面写的关于 sbt 的内容,你必须知道 specs2 默认同时运行你的规范的所有示例。

    您仍然可以声明,对于给定的规范,示例必须按顺序执行。为此,您只需在规范的开头添加 sequential

    class WriteAndReadSpec extends Specification{
      val file = new File("testFiles/tmp.txt")
    
      sequential
    
      "WriteAndRead" should {
       ...
      }
    }
    

    【讨论】:

    • 这是拼图中缺失的部分。实际上,即使没有其他答案建议的自定义 Build.scala ,它也可以工作。我猜 SBT 并行性是跨单独的测试文件而不是在单个文件中。
    • 是的,sbt 在测试之间控制这一点,顺序是在测试用例中使用的正确方法。保持它接近测试规范也更有意义,因为它会被隐式记录。
    【解决方案2】:

    套件的固定测试顺序可能导致测试用例的相互依赖和维护负担。

    我更愿意在不接触文件系统的情况下进行测试(无论是业务逻辑还是序列化代码),或者如果这是不可避免的(如测试与文件提要的集成),那么我会使用创建临时文件:

    // Create temp file.
    File temp = File.createTempFile("pattern", ".suffix");
    // Delete temp file when program exits.
    temp.deleteOnExit();
    

    【讨论】:

      【解决方案3】:

      wiki link Pablo Fernandez 给出的 his answer 非常好,尽管示例中有一个小错误可能会导致错误(尽管作为一个 wiki,我可以并且确实纠正了它)。这是一个project/Build.scala,它实际上编译并生成了预期的过滤器,尽管我实际上并没有通过测试进行尝试。

      import sbt._
      import Keys._
      
      object B extends Build
      {
        lazy val root =
          Project("root", file("."))
            .configs( Serial )
            .settings( inConfig(Serial)(Defaults.testTasks) : _*)
            .settings(
               libraryDependencies ++= specs,
               testOptions in Test := Seq(Tests.Filter(parFilter)),
               testOptions in Serial := Seq(Tests.Filter(serialFilter))
             )
            .settings( parallelExecution in Serial := false : _*)
      
        def parFilter(name: String): Boolean = !(name startsWith "WriteAndReadSpec")
        def serialFilter(name: String): Boolean = (name startsWith "WriteAndReadSpec")
      
        lazy val Serial = config("serial") extend(Test)
      
        lazy val specs = Seq(
              "org.specs2" %% "specs2" % "1.6.1",
              "org.specs2" %% "specs2-scalaz-core" % "6.0.1" % "test"
            )
      }
      

      【讨论】:

      • 感谢您指出这是一个项目/Build.scala 文件,正在为此苦苦挣扎。在看到我的测试之前(运行串行:测试时),必须将过滤器更改为使用“包含”而不是“开始”。不幸的是,我仍然得到不可预测的行为,所以我猜它仍然在并行运行。
      【解决方案4】:

      似乎还有第三种选择,即将串行测试分组到一个配置中,并分别运行它们,同时并行运行其余测试。

      检查this wiki,查找“应用到并行执行”

      【讨论】:

        【解决方案5】:

        其他答案解释了如何使用使它们按顺序运行。

        虽然它们是有效的答案,但我认为最好更改您的测试以让它们并行运行。(如果可能)

        在您的示例中 - 为每个测试使用不同的文件。 如果您涉及数据库 - 使用不同(或随机)的用户(或任何你可以的隔离) 等等……

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-19
          • 2016-10-29
          • 2019-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多