Unit-тестирование#
При необходимости проверки работоспособности отдельных частей исходного кода имеется возможность реализации unit-тестирования на основе ScalaTest.
Для создания набора тестов создайте класс, который будет наследоваться от LangFunSuite, ApiTest или других классов, в которые подмешаны трейты из ScalaTest.
Совет
Для дополнительной информации смотрите библиотеку unit тестирования: scalatest.
Создание класса с тестами#
Перейдите в окно проекта.
Выберете целевой модуль.
Перейдите в папку с исходными кодами:
[module_name]/src/test/scalaСовет
Создать недостающую папку можно из контекстного меню в idea
New > Directory.Создайте пакет
ru.bitec.app.[module_name].Создайте тестовый класс:
class Lesson1Test extends LangFunSuite{ test("HelloWorld"){ println("hello world") } }
Совет
Запустите тест из контекстного меню, для этого:
Переведите курсор на декларацию функции или класса, если нужно запустить все объявленные тесты класса.
В контекстном меню выполните операцию „Debug“ для запуска в режиме отладки или „Run“ для простого запуска.
Подробнее смотрите выполнение тестов в руководстве idea.
Примечание
Существуют два специализированных базовых класса для тестовых случаев:
LangFunSuite- используется для тестов, которые не нуждаются в контроллерах бизнес логики.Данные тесты не могут использовать
Api,Pkgи не имеют подключения к базе данных по умолчанию.ApiTest- в данном тексте доступен контекст автономной бизнес логики. Тестовые случаи могут использоватьApi,Pkgобъекты. При этом запуск теста становится медленней из за необходимости инициализировать контекст.
Базовые Assert методы#
Трейт Assertions содержит основные методы для проверки предположений.
Assert(condition: Boolean).
Этот метод проверяет условие. Если переданное условие возвращает true, то метод завершается нормально, иначе выбрасывает ошибку TestFailedException.
Пример:
test("создание объекта класса Btk_SomeClass") {
try {
val rop = Btk_SomeClassApi().insert()
assert(Btk_SomeClassExtApi().findSomeClassExt(rop).isDefined)
} finally {
session.rollback()
}
}
Данный тест проверяет, что при создании объекта Btk_SomeClass для него создаётся расширение Btk_SomeClassExt.
Если расширение не было создано, то тест не будет пройден.
В консоль будет выведен
текст ошибки :
Btk_SomeClassExtApi.apply().findSomeClassExt(rop).isDefined was false
В assert можно передать дополнительный комментарий, который будет добавляться к тексту ошибки:
test("создание объекта класса Btk_SomeClass") {
try {
val rop = Btk_SomeClassApi().insert()
assert(rop.get(_.dBeginDate).isNotNull, "При создании не установилась дата начала.")
assert(Btk_SomeClassExtApi().findSomeClassExt(rop).isDefined, "При создании не зарегистрировалось расширение.")
} finally {
session.rollback()
}
}
assertResult(expected: Any)(actual: Any).
Сравнивает ожидаемое ожидаемое значение с переданным:
test("parseGtkSessionClientFullName") {
val x = WorkSessionClientHelper.parseGtkSessionClientFullName("DESkTOP-23565:8080#E1@123-45")
assert(x.isDefined)
assertResult("DESkTOP-23565:8080")(x.get._1)
assertResult("E1")(x.get._2)
assertResult("123-45")(x.get._3)
}
assertThrows[T <: AnyRef](f: => Any).
Используется, когда нужно удостоверится, что при определенных методах тестируемый код выдаст ошибку:
test("data.oaObjQty.isEmpty") {
val data = new Bs_DistrData()
assertThrows[AppException] {
Bs_DistributionPkg().distribQty(data)
}
}
assume(condition: Boolean).
Метод aналогичен методу assert, но в случае, когда не выполняется условие, не завершается ошибкой, а отменяет тест. Так же может содержать пояснительный комментарий:
assume(database.isAvailable, "База данных не доступна.")
assume(database.getAllUsers.count === 9)
intercept[T <: AnyRef](f: => Any).
Метод aналогичен методу assertThrows, но позволяет получить ошибку ожидаемого типа для более детальной проверки:
val vEx = intercept[AppException] {
_api.validateOnBeforeManualInsert(ropDuplicate)
}
assert(vEx.getMessage.startsWith("Ошибка. Уже существует запись с классом типа объектов:"))
Matchers#
Трейт Matchers позволяет использовать в тестах комбинаторы вроде shouldBe вместо обычного assert, улучшая читаемость кода.
По умолчанию к ApiTest и LangFunSuite Matchers не подключен, поэтому чтобы использовать его методы, добавьте его в объявлении класса:
class Bs_AccApiTest extends ApiTest with Matchers {
test("set level on insert") {
val rop = api.insert()
rop.get(_.nLevel) should ===(1.nn)
}
}
Для дополнительной информации смотрите в руководстве пользователя: matchers.
Некоторые примеры:
Проверка размера и длины.
Для проверки размера и длины используйте:
<проверяемый объект> should have length (<ожидаемое значение>);
<проверяемый объект> should have size (<ожидаемое значение>).
Пример:
test("проверка размера массива") {
val result = getArgs()
result should have length (3)
}
Проверка строк:
на наличие подстроки:
string should startWith ("Hello")
string should endWith ("world")
string should include ("seven")
с использованием регулярных выражений:
string should startWith regex ("Hel*o")
string should endWith regex ("wo.ld")
string should include regex ("wo.ld")
проверка всей строки на соответствие регулярному выражению:
string should fullyMatch regex ("""(-)?(\d+)(\.\d*)?""")
Сравнения больше/меньше/равно:
Можно сравнивать объекты любого типа, кроме тех, которые могут быть преобразованы в Ordered[T]. Для сравнения списков, используйте greater than, less than, greater than or equal, less than or equal to a value of type T
one should be < (7)
one should be > (0)
one should be <= (7)
one should be >= (0)
с использованием регулярных выражений:
string should startWith regex ("Hel*o")
string should endWith regex ("wo.ld")
string should include regex ("wo.ld")
проверка всей строки на соответствие регулярному выражению:
string should fullyMatch regex ("""(-)?(\d+)(\.\d*)?""")