2011-11-06 110 views
25

我注意到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 
    } 
} 

回答

35

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

您仍然可以声明,对于给定的规范,必须按顺序执行示例。要做到这一点,你只需添加sequential您的规格的开头:测试的套房

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

    sequential 

    "WriteAndRead" should { 
    ... 
    } 
} 
+1

这是拼图的缺失部分。事实上,即使没有自定义Build.scala建议的其他答案,它也可以工作。我猜SBT并行性是跨越单独的测试文件而不是单个文件。 – Pengin

+0

是的,sbt在测试之间控制这个,sequential是在测试用例中正确使用的。保持接近测试规格更有意义,因为那样会隐含记录。 –

2

似乎有一个第三个选项,其被分组在一个配置中,串行测试和单独运行它们,同时并行运行的其余部分。

检查this wiki,寻找“应用程序并行执行”

+0

链接不工作了! –

2

wiki linkPablo Fernandezhis answer中给出的很不错,虽然这个例子中有一个小错误可能会导致一次性错误(尽管作为一个维基,我可以修改它)。这是一个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" 
    ) 
} 
+0

感谢您指出这是一个项目/ Build.scala文件,并且一直在努力。必须在看到我的测试(运行serial:test)之前更改过滤器以使用'contains'而不是'startsWith'。不幸的是,我仍然得到不可预知的行为,所以我猜猜它仍然在平行运行。 – Pengin

3

固定的顺序可能会导致测试用例的相互依赖性和负担维护。我倾向于在不接触文件系统的情况下进行测试(不管是业务逻辑还是序列化代码),或者如果它不可避免(如测试与文件馈送的集成),那么将使用创建临时文件:

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

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

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

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