Моя любимая функция в JUnit — это Правила . С помощью Правил вы можете манипулировать выполнением теста, оборачивая свой собственный код вокруг выполнения теста. Я использовал это для настройки баз данных для тестирования , чтобы убедиться, что они выполняются в EDT , для ограничения допустимого времени выполнения теста и для настройки и удаления различных других ресурсов.
Поэтому, естественно, при работе со ScalaTest я очень скоро захотел получить что-то эквивалентное Правилам. Хотя при поиске «Правила ScalaTest» вы найдете немногое, его на самом деле довольно легко реализовать.
Независимо от того, какие тесты вы пишете с помощью ScalaTest, в конце дня будет вызван метод def withFixture (aTest: NoArgTest) с вашим тестом для выполнения. «Ваш тест» означает в случае FunSuite тестирование содержимого между фигурными скобками, которые вы передаете методу теста.
Реализация withFixture наконец выполнит ваш тест. Поэтому все, что вам нужно сделать, чтобы получить эквивалент правила JUnit, это переопределить с помощью Fixture. Давайте попробуем:
class ExampleTest extends FunSuite {
override def withFixture(test : NoArgTest){
println
println("before")
super.withFixture(test)
println("after")
}
test("example test"){
println("succeding test")
}
test("example failing test"){
println("failing test")
fail("embrace failure")
}
}
Это производит следующий вывод на консоль:
before succeding test after before failing test
Как видите, если вы хотите что-то делать после теста, вам лучше поместить его в блок finally, чтобы он выполнялся независимо от того, провалился тест или нет.
Хотя это работает, мы не хотим явно переопределять withFixture каждый раз, когда нам нужно наше «правило». Решение этого состоит в том, чтобы извлечь это в черту:
trait ExampleRule extends AbstractSuite {
self : Suite =>
override abstract def withFixture(test : NoArgTest) {
println
println("before")
try {
ExampleRule.super.withFixture(test)
} finally {
println("after")
}
}
}
class Example2Test extends FunSuite with ExampleRule {
test("example test") {
println("succeding test")
}
test("example failing test") {
println("failing test")
fail("embrace failure")
}
}
Эта черта расширяет AbstractSuite, что делает withFixture доступным. Он имеет собственный тип Suite, чтобы гарантировать, что он смешивается только с тестовыми наборами.
Итак, как это решение сравнивается с реализацией правила JUnit? С помощью правила Junit мы должны создать собственно правило плюс экземпляр Statement. С ScalaTest мы расширяем только одну черту. Кроме того, поскольку все это стандартное наследование Scala, не требующее отражения, поэтому довольно просто узнать, как это работает. В то время как, как и почему выполняется правило, довольно сложно из одного источника. Наконец, вы можете явно контролировать порядок, в котором применяются ваши черты, управляя порядком, в котором вы помещаете их в предложение extends:
trait Example3Rule extends AbstractSuite {
self : Suite =>
override abstract def withFixture(test : NoArgTest) {
println("3 before")
try {
Example3Rule.super.withFixture(test)
} finally {
println("3 after")
}
}
}
@RunWith(classOf[JUnitRunner])
class Example3Test extends FunSuite with Example3Rule with ExampleRule{
test("example test") {
println("succeding test")
}
test("example failing test") {
println("failing test")
fail("embrace failure")
}
}
before 3 before succeding test 3 after after before 3 before failing test 3 after after
С Junit Rules в настоящее время нет готового способа сделать это, но функция для достижения этого находится в разработке .
От http://blog.schauderhaft.de/2011/08/28/manipulation-test-execution-with-scalatest/