Scala 为什么Specs2以随机顺序运行这些“顺序”测试?

Scala 为什么Specs2以随机顺序运行这些“顺序”测试?,scala,integration-testing,specs2,playframework-2.1,Scala,Integration Testing,Specs2,Playframework 2.1,有一个旧的数据库测试套件,我正试图从规范迁移到它。然而,Specs2以一种奇怪的顺序运行测试(在我看来),这会破坏测试,因为它们会更改数据库状态,并运行某些代码两次 下面是测试的简化版本。据我所知,测试应该按以下顺序运行:(因为我指定了顺序): !222,!333,!444 然而,实际发生的是,它们是按以下顺序执行的: !333,!222,!444 以下是测试: object IncludedSpec extends Specification { sequential println(

有一个旧的数据库测试套件,我正试图从规范迁移到它。然而,Specs2以一种奇怪的顺序运行测试(在我看来),这会破坏测试,因为它们会更改数据库状态,并运行某些代码两次

下面是测试的简化版本。据我所知,测试应该按以下顺序运行:(因为我指定了顺序):
!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
还有我的两个问题:

  • 为什么不是
    !222
    先执行吗

  • ssssstart eeend
    如何可能输出两次?等级库是一个对象,不会创建两次吗

  • 奇怪的是,如果我从测试中移除副作用-即移除variableN并用
    ok
    替换测试体-测试将以正确的顺序运行

    版本详细信息:我正在使用Paly Framework 2.1-SNAPSHOT(2012年10月28日的203df0e版本)和Scala 2.10.0-RC1运行这些测试。我认为与Play捆绑在一起的Specs2版本是1.12版,因为
    inline
    方法是可用的,并且它是在1.12(-SNAPSHOT)中添加的,请参阅,没有更高的Specs2版本

    (哦,如果你认为我应该完全重写测试,那就看看这个问题:)

    (更新:这并不适用于我真正的相当大的规格。它仍然按看似随机的顺序执行,SPECs2似乎开始在中间某个地方。-但是,当我用下面的10个或20个例子做了一个小规格的替换时,它确实导致了规范执行的正确顺序。奇怪)

    这里有一个局部解决方法,但不是真正的答案:

    在测试片段之前,在中使用
    ,而不是
    >
    。然后按照正确的顺序执行测试。(但是
    ssstart eeend
    仍然会发生两次。)

    因此,这是预期的:(我在
    中用
    替换了某些


    我的困惑如下:

    一,

    我认为
    中的
    >
    之间的区别在于:
    中的
    只能出现在测试片段之前(即,
    {…x必须\==y…}
    块)。但是
    >
    既可以出现在整个示例(带有嵌套测试片段)之前,也可以出现在测试片段之前

    因此,当我在编写
    >
    时,Specs2并不直接知道会发生什么。但我不知道为什么这会改变测试执行顺序。除非Specs2需要…在
    {…}
    块中执行一些代码来找出答案?但是Specs2不使用反射吗?这感觉很奇怪

    二,


    如果测试完全没有副作用(在这种情况下,更新no shared
    var
    s)。或者,如果所有测试都有副作用。那么,据我所知,它们是按照正确的顺序执行的。但是,如果有些测试没有副作用,除了读取共享的
    var
    ,那么它们似乎是在写入
    var
    的测试之后执行的(如果使用
    >
    而不是
    中的
    )这也让人觉得很奇怪。无论如何,我想很快我就会开始将我的测试移植到Specs2,并将
    >
    替换为
    中的
    :-)

    最初,在Specs2中,您可以创建以下内容:

    1-在{1 must.==1}
    中带有
    的示例:
    “这是一个示例”

    2-带有
    >
    的示例:
    “这是一个示例”>{1 must==1}

    3-带有
    >>

    "this system should" >> {
      "do something" >> ok
      "do something else" >> ok
    }
    
    重要的是,
    中的
    仅用于示例,并接受任何可以转换为
    结果的内容。另一方面,
    >
    可用于示例和示例组(具有统一的嵌套样式),因此它接受类型为
    Example
    Result
    的值

    现在,当您想执行以下操作时,事情开始变得有点复杂:

    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
    的表达式都具有类型
    Unit
    。但是他们在做两件完全不同的事情!第一个是构建示例,因此需要立即计算此表达式以构建
    规范
    。第二个是创建
    示例的主体,稍后将执行(或者如果示例被过滤掉,则可能永远不会执行)。有两件事,同一个操作符不能工作

    因此决定
    >>(block:=>Unit)
    表示“这通过副作用构建了一组示例”,而
    in(expectations:=>Unit)
    表示“这构建了一个
    示例的主体
    可能具有副作用的预期

    现在,当这更好地解释了为什么打印语句会出现奇怪的顺序时:

    ..222
    ....333
    ......! 333 doing some tests and setting variableN
    ....444
    ....555
    
    首先打印,因为它们包含在类型为
    Unit
    的块中,被解释为一组示例

    以及:

    因为它们是在类型为
    MatchResult[\u]
    的块中打印的,也就是说,它们被视为示例的主体

    我同意这是令人困惑的,我希望这一解释能从某种角度解释为什么事情是这样的。当然,另一个教训是“副作用是偷偷的,因为它们不会告诉你它们到底在做什么”

    因此,一般的specs2技巧是始终以适当的值结束块(除非使用
    foreach
    构造,如我的示例abo所示)
    ..222
    ....333
    ......! 333 doing some tests and setting variableN
    ....444
    ....555
    
    ....! 222 the first test
    ......! 444 testing variableN