2011-11-06 187 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

其他答案解釋瞭如何使用讓他們順序運行。

雖然他們是有效答案,但我認爲最好是更改測試以讓它們並行運行。(如果可能的話)

在你的例子中 - 爲每個測試使用不同的文件。 如果你有數據庫涉及 - 使用不同的(或隨機)用戶(或任何隔離,你可以) 等...