3

Specs からSpecs2に移行しようとしている古いデータベース テスト スイートがあります。ただし、Specs2 は (私の観点からは) 奇妙な順序でテストを実行します。これにより、データベースの状態が変更され、特定のコードが 2 回実行されるため、テストが中断されます。

テストの簡略化されたバージョンを以下に示します。私が理解している限り、テストは次の順序で実行する必要があります: (シーケンシャルを指定したため):
! 222, ! 333,! 444
しかし、実際には、次の順序で実行されます:
! 333, ! 222,! 444

テストは次のとおりです。

object IncludedSpec extends Specification {
  sequential
  println("sssstart")

  "IncludedSpec" should {

    println("..222")
    "context free block" >> {
      println("....! 222 the first test")
      1 === 1
    }

    var variableN = 0

    "block with context" >> {
      println("....333")
      "using one variable" >> {
        println("......! 333 doing some tests and setting variableN")
        variableN = 123
      }

      println("....444")
      "using it again" >> {
        println("......! 444 testing variableN")
        variableN === 123
      }
      println("....555")
    }
  }

  println("eeeend")
}

すべてのprintln出力は次のとおりです。

sssstart
eeeend
sssstart
eeeend
..222
....333
......! 333 doing some tests and setting variableN
....444
....555
....! 222 the first test
......! 444 testing variableN

そして私の2つの質問:

  1. ! 222最初に実行されないのはなぜですか?

  2. sssstart eeeend2回出力される可能性はありますか?仕様はオブジェクトであり、2 回作成されていませんか?

奇妙なことに、テストから副作用を取り除くと、つまりvariableNを削除してテスト本体を置き換えると、テストokは正しい順序で実行されます。

バージョンの詳細: これらのテストは、Paly Framework 2.1-SNAPSHOT (2012 年 10 月 28 日のバージョン 203df0e) と Scala 2.10.0-RC1 で実行しています。Play にバンドルされている Specs2 のバージョンはバージョン 1.12 であると思います。inlineメソッドが使用可能であり、1.12(-SNAPSHOT) で追加されたためです。https://github.com/etorreborre/specs2/issues/87を参照し、それ以降はありませんSpecs2 バージョン。

(テストを完全に書き直す必要があると思われる場合は、代わりにこの質問を見てください:相互に依存するテストを使用して Specs2 データベース テストを設計する方法は? )

4

2 に答える 2

10

もともと、specs2 では、次のものを作成できました。

1 - の例in:"this is an example" in { 1 must_== 1 }

2 - 例>>:"this is an example" >> { 1 must_== 1 }

3 - 例のブロック>>

"this system should" >> {
  "do something" >> ok
  "do something else" >> ok
}

重要なことは、inは例のみのために予約されており、 に変換できるものなら何でも受け入れたことResultです。一方、は例と例のグループの両方に使用できるため (入れ子のスタイルを統一するため)、 or>>型の値を受け入れます。ExampleResult

次のことをしたいとき、物事はもう少し複雑になり始めました:

1 -foreach例のグループを作成するために使用します

"this group has 5 examples" in {
  (1 to 5) foreach { i => "example "+i >> ok }
}

2 -foreach期待のグループを作成するために使用します

"this example has 5 expectations" in {
  (1 to 5) foreach { i => i must_== i }
}

問題は、foreach両方の 2 つの式に type があることUnitです。しかし、彼らは2つの非常に異なることをしています! 1 つ目は例を作成しているため、この式をすぐに評価して を作成する必要がありますSpecification。2 番目のものは an の本体を作成しており、Example後で実行されます (たとえば、例が除外されている場合は実行されない可能性があります)。同じ operator を持つ 2 つのことは機能し>>ません。

そこで、これ>>(block: =>Unit)は「これは副作用によって例のグループを構築する」という意味であり、 「これはおそらく期待を持っている副作用in(expectations: =>Unit)の本体を構築する」という意味であると決定されました。Example

ここで、print ステートメントで奇妙な順序が表示されている理由をもう少しよく説明すると、次のようになります。

..222
....333
......! 333 doing some tests and setting variableN
....444
....555

Unit例のグループとして解釈され、 type のブロックに含まれているため、最初に出力されます。

と :

....! 222 the first test
......! 444 testing variableN

これらは type のブロックにあるため、結果として出力されますMatchResult[_]。つまり、例の本体と見なされます。

これが紛らわしいことに同意します。この説明が、なぜ物事がそのようになっているのかについての何らかの視点をもたらすことを願っています. もちろん、もう 1 つの教訓は、「副作用は、実際に何をしているのかを教えてくれないため、卑劣である」ということです。

したがって、specs2 の一般的なヒントは、ブロックを常に適切な値で終了することです (foreach上記の例に示すような構造を使用しない限り)。たとえばok、変数の割り当てを行うブロックの最後に追加すると、問題が解決するはずです。

于 2012-11-02T10:40:32.823 に答える