Статьи

Тестирование с помощью Scala

При изучении нового языка или структуры один из моих первых вопросов в настоящее время: а как насчет тестирования? Очевидно, я просил это и для Скалы.

Если есть на что жаловаться, я думаю, это еще раз большое количество вариантов.

JUnit

Scala хорошо совместим с Java, и в него входит популярная среда тестирования Junit. Вы можете просто написать свои тесты, используя JUnit, как вы привыкли, но заменить классы Java на классы Scala

01
02
03
04
05
06
07
08
09
10
11
class ConnectionTest {
    import org.junit.Test
    import org.junit.Assert._
  
    @Test
    def connection_Equals_itself() {
        val con = Connection(Corner(), Corner())
        assertEquals(con, con)
        assertEquals(con.hashCode, con.hashCode)
    }
}

Это хорошо работает. Но я обещаю, что как только вы привыкнете к совершенству Scala, вы захотите использовать его и в своих тестах. Итак, время взглянуть на некоторые тестовые рамки Scala. Существуют две основные тестовые среды для Scala: спецификации и ScalaTest .

ScalaTest

Я выбрал ScalaTest, потому что он допускает множество различных стилей тестирования. Так много возможностей для экспериментов. Стиль, который я предпочитаю, основан на «особенностях». В отличие от JUnit отдельные тесты не определяются в отдельных методах, но все тесты размещаются непосредственно внутри тела класса и, следовательно, выполняются после создания экземпляра класса. (Судя по API, есть способы отрегулировать это , но я еще не исследовал их.)

Тесты сгруппированы по функциям, и каждый тест называется сценарием. Поскольку тесты — это не методы, а вызовы методов, вы не можете использовать имя метода в качестве имени теста. Вместо этого вы предоставляете параметр String. Это позволяет использовать более понятные имена. По крайней мере, я считаю это хорошей вещью. Одна из особенностей небольшого проекта, над которым я работаю, выглядит следующим образом.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
class ImageComparisonTest extends FeatureSpec {
  
    feature("a user can compare the screenshot of a swing component with an image stored on disk") {
      scenario("comparing a component to a NOT matching image") {
            pending
        }
        scenario("comparing a component to a NOT existing image in headless mode") {
            pending
        }
        scenario("comparing a component to a NOT existing image in withhead mode") {
            pending
        }
    }
}

Trait FeatureSpec делает функцию и методы сценария доступными. «Ожидающие» операторы помечают тест как … ну … ожидающий, потому что ни тест, ни код еще не реализованы. Ожидающие тесты отмечены как «Игнорируемые». Самый простой способ сделать утверждения в тесте — вызвать assert или другие методы объекта Assertions . Но можно также смешивать различные черты для разных стилей определения утверждений. Например, ShouldMatchers предоставляют хороший DSL, разрешающий такие выражения:

1
(5 * 23) should equal (115)

Этот стиль указания утверждений также гарантирует действительно хорошие сообщения об ошибках в случае неудачного утверждения. Этот тест

01
02
03
04
05
06
07
08
09
10
class SomeTest extends FeatureSpec with ShouldMatchers
    feature ("ShouldMatcher provide nice error messages"){
     scenario ("Making a correct assertion"){
      (5 * 23) should equal (115)
     }
     scenario ("Making a stupid assertion"){
      (5 * 23) should equal (116)
     }
    }
}

приводит к появлению этого сообщения об ошибке при выполнении:

1
2
3
[error] Test Failed: Feature: ShouldMatcher provide nice error messages Making a stupid assertion
org.scalatest.TestFailedException: 115 did not equal 116
        at org.scalatest.matchers.Matchers$class.newTestFailedException(Matchers.scala:148)

В тестах JUnit у меня иногда есть пустые строки или даже комментарии в моих тестах, чтобы визуально отделить настройку от действительного действия, которое я хочу проверить, и утверждения. С ScalaTest у вас есть гораздо более хороший способ сделать это: свойство GivenWhenThen. С его помощью вы не размещаете комментарии в своем коде, а вызываете метод со строковым параметром, который в итоге снова окажется в выводе вашего теста:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
class SomeTest extends FeatureSpec with ShouldMatchers with GivenWhenThen
    feature ("ShouldMatcher provide nice error messages"){
     scenario ("Making a correct assertion"){
      given ("a number")
      val number = 5
      and ("an other number")
      val otherNumber = 23
      when ("multiplying one with the other")
      val result = number * otherNumber
      and ("the other way round")
      val otherResult = otherNumber * number
      then ("the results will be the same")
      result should equal (otherResult)
     }
    }
}

Хотя в этом тривиальном случае и со слабой подсветкой синтаксиса моего блога это может немного отвлечь, это действительно хорошая форма тестов комментирования в строке.

Конечно, вы не просто пишете тесты, вы хотите, чтобы они также выполнялись. Существуют Runners для JUnit и TestNG, так что вы можете выполнять свои ScalaTests с помощью инфраструктуры тестирования, к которой вы привыкли. Но я настоятельно рекомендую использовать sbt для непосредственного выполнения ваших тестов. Sbt — это простой инструмент для сборки . Установка чрезвычайно проста: вы запускаете ее, вводите команду ~ test и она запускает все ваши тесты всякий раз, когда вы сохраняете свой код. Действительно приятно, тем более, что он намного быстрее, чем компиляторы scala внутри IDE, которые я видел до сих пор.

Это был лишь небольшой проблеск возможностей тестирования с помощью Scala (Test). Я с нетерпением жду, чтобы исследовать еще больше.

Ссылка: тестирование со Scala от нашего партнера JCG Йенса Шаудера в блоге Schauderhaft .

Статьи по Теме :