【问题标题】:Logging unit test name in Scala在 Scala 中记录单元测试名称
【发布时间】:2019-01-15 23:23:07
【问题描述】:

我想在 Scala 中自动记录单元测试名称。org.junit.rules.TestName 的解决方案在 Java 中运行良好,但在 Scala 中不行。

考虑以下代码sn-p:

import org.junit._
import org.junit.rules.TestName

class ScalaUnitTestExample {
    @Rule val testName = new TestName

    @Before def printTestCaseNameBefore() {
        print("\nStart of test case " + testName.getMethodName)
    }

    @After def printTestCaseNameAfter() {
        print("\nEnd of test case " + testName.getMethodName)
    }

    @Test
    def checkAddition() {
        Assert.assertEquals(5, 2 + 3)
    }

    @Test
    def checkMultiplication() {
        Assert.assertEquals(6, 2 * 3)
    }
}

编译正常,但运行时收到以下错误消息:

There was 1 failure:
1) initializationError(ScalaUnitTestExample)
java.lang.Exception: The @Rule 'testName' must be public.
        at org.junit.internal.runners.rules.RuleFieldValidator.addError(RuleFieldValidator.java:90)
        (...)
        at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)

FAILURES!!!
Tests run: 1,  Failures: 1

Java 对应项按预期工作。

我已经尝试过以下方法(根据Using JUnit @Rule with ScalaTest (e.g. TemporaryFolder)):

val _testName = new TestName
@Rule def testName = _testName

但这并没有真正帮助。在此版本中,测试用例运行,但 {testName} 结果始终为 {null}。

Scala 中的默认访问规则是公共的,因此没有public 关键字。另一方面,JUnit 框架似乎认为它是非公开的。

有谁知道如何解决这个问题?另一个类似的解决方案也可以!谢谢!

【问题讨论】:

  • 为什么不使用 ScalaTest 代替?您将能够在日志中看到测试名称,@Before@After 有替代名称。
  • 第一个选项的问题是val testName 定义了一个字段和一个getter 方法(用Java 术语);默认情况下注释转到字段(但这可以更改:参见scala-lang.org/api/2.11.8/#scala.annotation.meta.package);该字段是私有的(Scala 根本不允许定义非私有字段),但 JUnit 要求它是公共的。令我惊讶的是,第二个选项不起作用。

标签: scala junit


【解决方案1】:

您知道 scala 默认访问规则是公共的,但 scala 有一个技巧,该字段是私有的,它会生成 getter 和 setter,这就是 @Rule 在您的代码中不起作用的原因。

你可以使用它来工作

import org.junit._
import org.junit.rules.TestName


    class ScalaUnitTestExample {
      var _testName: TestName = new TestName

      @Rule
      def testName = _testName
      def testName_=(aTestName: TestName) {_testName = aTestName}

      @Before def printTestCaseNameBefore() {
        print("\nStart of test case " + testName.getMethodName)
      }

      @After def printTestCaseNameAfter() {
        print("\nEnd of test case " + testName.getMethodName)
      }

      @Test
      def checkAddition() {
        Assert.assertEquals(5, 2 + 3)
      }

      @Test
      def checkMultiplication() {
        Assert.assertEquals(6, 2 * 3)
      }
    }

无论如何,使用 ScalaTest 或 Specs2 会让您的生活更轻松。

【讨论】:

  • 感谢您的提示!不幸的是,您的解决方案结果总是null 值。我会检查其他提案。
  • 我不知道可能是什么问题。我自己运行它并为我工作。
  • 感谢您添加截图!正如我所见,您使用的是 Linux;我有 Windows 7。您使用的是哪些工件版本?我的Scala版本是2.11.7,JUnit版本是4.9。
  • 克隆这个 repo 并运行“sbt test”它应该可以在 Windows 中运行。 github.com/jonasanso/junit-test-scala
  • 我做了,但结果是一样的:测试用例开始 null 测试用例结束 null 测试用例开始 null 测试用例结束 null[info] 通过:总计 2,失败 0,错误 0 ,通过2【成功】总时间:22s,2016.03.22完成。 18:01:52
【解决方案2】:

解决方案(使用简单的 hack):将方法名称逻辑放入用 Java 编写的基类中。 Java源码(UnitTestBase.java):

import org.junit.*;
import org.junit.rules.TestName;

public class UnitTestBase {
    @Rule public TestName testName = new TestName();

    @Before public void printTestCaseNameBefore() {
        System.out.println("Start of test case " + testName.getMethodName());
    }

    @After public void printTestCaseNameAfter() {
        System.out.println("End of test case " + testName.getMethodName());
    }
}

Scala 源码 (ScalaUnitTestExample.scala):

import org.junit._

class ScalaUnitTestExample extends UnitTestBase {
    @Test
    def checkAddition() {
        Assert.assertEquals(5, 2 + 3)
    }

    @Test
    def checkMultiplication() {
        Assert.assertEquals(6, 2 * 3)
    }
}

编译:

scalac -cp .;junit-4.9.jar UnitTestBase.java ScalaUnitTestExample.scala

运行:

scala -cp .;junit-4.9.jar org.junit.runner.JUnitCore ScalaUnitTestExample

结果:

JUnit version 4.9
.Start of test case checkMultiplication
End of test case checkMultiplication
.Start of test case checkAddition
End of test case checkAddition

Time: 0,005

OK (2 tests)

【讨论】:

    【解决方案3】:

    使用 JUnit 4.12,我使用了 @Jonas Anso 的解决方案,它适用于该版本,但在 4.8 和 4.10 中不起作用。 我们必须在方法上设置@Rule,而不是在字段上,这似乎在 4.8 和 4.10 中被忽略了。 也只需要 getter。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-28
      • 1970-01-01
      • 2023-03-18
      • 2013-09-09
      相关资源
      最近更新 更多