2016-03-22 4 views
0

Я хочу автоматически регистрировать имена тестов модулей в Scala. Решение с org.junit.rules.TestName отлично работает на Java, но не в Scala.Имя тестового устройства в Scala

Рассмотрим следующий фрагмент кода:

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, похоже, считает ее непубличной.

Кто-нибудь знает, как преодолеть эту проблему? Другое подобное решение также будет прекрасным! Спасибо!

+0

Почему вы не используете ScalaTest вместо этого? Вы сможете увидеть имя теста в журналах, и есть альтернативы для '@ Before' и' @ After'. – Zyoma

+0

Проблема с первым вариантом заключается в том, что 'val testName' определяет как поле, так и метод getter (в терминах Java); аннотация указывается в поле по умолчанию (но это можно изменить: см. http://www.scala-lang.org/api/2.11.8/#scala.annotation.meta.package); поле является приватным (Scala не позволяет определять неличные поля вообще), но JUnit требует, чтобы он был общедоступным. Удивительно, что второй вариант не работает. –

ответ

0

Решение (с легким взломом): поместите логику имени метода в базовый класс, написанный на 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) 
    } 
} 

Compile:

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) 
1

Как известно, правило доступа по умолчанию scala является общедоступным, но scala делает трюк, поле является частным и генерирует геттеры и сеттеры, и именно по этой причине @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) 
     } 
    } 

enter image description here

Во всяком случае, используя ScalaTest или Specs2 бы сделать вашу жизнь проще.

+0

Спасибо за подсказку!К сожалению, ваше решение всегда имеет значение «null». Я проверю другие предложения. –

+0

Я не знаю, в чем проблема. Я сам управлял им и работал на меня. –

+0

Спасибо за добавление скриншота! Как я вижу, вы используете Linux; У меня Windows 7. Какие версии артефактов вы используете? Моя версия Scala - 2.11.7, а версия JUnit - 4.9. –

Смежные вопросы