【问题标题】:Can you dynamically generate Test names for ScalaTest from input data?您可以从输入数据动态生成 ScalaTest 的测试名称吗?
【发布时间】:2015-04-26 11:08:51
【问题描述】:

我有许多通过相同 ScalaTest 单元测试运行的测试数据集。如果每个测试数据集都是它自己的一组命名测试,我会很高兴,所以如果一个数据集失败了其中一个测试,我会确切地知道它是哪一个,而不是去一个单一的测试并查看它失败的文件。我似乎无法找到在运行时生成测试名称的方法。我查看了基于属性和表的测试,目前正在使用should behave like 来共享固定装置,但这些似乎都不能满足我的要求。

我是不是没有在 ScalaTest 中发现正确的测试方法,或者这不可能?

【问题讨论】:

    标签: scala scalatest


    【解决方案1】:

    如何使用 ScalaTest 的线索机制,以便任何测试失败都可以作为线索报告正在使用的数据集?

    您可以使用 Assertions 提供的 withClue 构造, ScalaTest 中的每个样式特征都对其进行了扩展,以添加 测试失败或取消报告的额外信息。

    另请参阅AppendedClues 上的文档

    【讨论】:

    • 这就是我现在正在做的事情。我有一个测试并循环测试集,并为每次迭代设置 withClue。我宁愿有 n 个单独的测试,每个测试的名称都包含在测试名称中
    • 为什么?使用不同的测试名称,您将能够做什么,否则您无法做到?
    • 测试集是不同的输入场景。很高兴知道我是否在基于测试名称而不是测试输出的场景中失败。 IE。我有集scenario1scenario2。有了线索,对"test sets should pass condition X" 进行了一项测试,如果失败,我必须查看输出以查看scenario1scenario2 是否失败。使用单独生成的测试名称,测试名称会显示给我,例如"scenario2 should pass condition X"
    【解决方案2】:

    您可以在测试名称中使用 scala 字符串替换。使用behavior functions,这样的事情会起作用:

    case class Person(name: String, age: Int)
    
    trait PersonBehaviors { this: FlatSpec =>
    
      // or add data set name as a parameter to this function
      def personBehavior(person: => Person): Unit = {
        behavior of person.name
    
        it should s"have non-negative age: ${person.age}" in {
          assert(person.age >= 0)
        }
      }
    }
    
    class TheTest extends FlatSpec with PersonBehaviors {
      val person = Person("John", 32)
    
      personBehavior(person)
    }
    

    这会产生如下输出:

    TheTest:
    John
    - should have non-negative age: 32
    

    【讨论】:

      【解决方案3】:

      您可以编写一个基础测试类,并为每个数据集扩展它。像这样的:

      case class Person(name: String, age: Int)
      
      abstract class MyTestBase extends WordSpec with Matchers {
      
        def name: String
        def dataSet: List[Person]
      
        s"Data set $name" should {
          "have no zero-length names" in {
            dataSet.foreach { s => s.name should not be empty }
          }
        }
      }
      
      class TheTest extends MyTestBase {
        override lazy val name = "Family" // note lazy, otherwise initialization fails
        override val dataSet = List(Person("Mom", 53), Person("Dad", 50))
      }
      

      产生这样的输出:

      TheTests:
      Data set Family
      - should have no zero-length names
      

      【讨论】:

      • 甚至没有考虑在测试名称中使用字符串插值。不错的方法
      • 谢谢 :-) 如果您想继续使用行为函数,请参阅下面我的其他答案。
      【解决方案4】:

      您可以使用 ScalaTest 编写动态测试用例,就像 Jonathan Chow 在他的博客中所写的那样:http://blog.echo.sh/2013/05/12/dynamically-creating-tests-with-scalatest.html

      但是,我总是更喜欢 WordSpec 测试定义,这也适用于动态测试用例,就像 Jonathan 提到的那样。

      class MyTest extends WordSpec with Matchers {
         "My test" should {
           Seq(1,2,3) foreach { count =>
             s"run test $count" in {
                count should be(count)
             }
           }
         }
      }
      

      运行此测试时,它会运行 3 个测试用例

      TestResults
        MyTest
          My test
            run test 1
            run test 2
            run test 3
      

      ps。您甚至可以使用同一个 count 变量在同一个 foreach 函数中执行多个测试用例。

      【讨论】:

        猜你喜欢
        • 2012-04-14
        • 2021-09-03
        • 2013-01-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多