Тестирование на основе свойств
ScalaCheck
«Тестирование на основе свойств» — бесплатный урок Scala for Backend Engineering & Functional Programming на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Scala for Backend Engineering & Functional Programming, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.
Что такое тестирование на основе свойств?
При тестировании на основе свойств Вы формулируете общее свойство, которое должно выполняться для всех входных данных, а фреймворк генерирует множество случайных входных данных, пытаясь опровергнуть это свойство. Такой подход находит крайние случаи, которые могут быть пропущены тестами, написанными вручную.
Пример и свойство
Тест на примере проверяет один случай: reverse(List(1,2,3)) == List(3,2,1). Свойство формулирует правило: двойное обращение списка возвращает исходный список для любого списка. Фреймворк проверяет это правило на сотнях сгенерированных списков.
ScalaCheck
ScalaCheck — библиотека тестирования свойств для Scala. Добавьте её как зависимость для тестирования; она интегрируется со ScalaTest.
libraryDependencies += "org.scalatestplus" %% "scalacheck-1-17" % "3.2.18.0" % TestforAll
Основная конструкция — forAll: она генерирует случайные значения и проверяет тело свойства для каждого из них. Здесь мы проверяем коммутативность сложения.
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class AddSpec extends AnyFlatSpec with Matchers with ScalaCheckPropertyChecks {
"addition" should "be commutative" in {
forAll { (a: Int, b: Int) =>
a + b shouldBe b + a
}
}
}Свойство обратного преобразования
Мощный шаблон — обратное преобразование: кодирование с последующим декодированием (или двойное обращение) должно возвращать исходное значение для любых входных данных.
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class RevSpec extends AnyFlatSpec with Matchers with ScalaCheckPropertyChecks {
"reverse" should "be its own inverse" in {
forAll { (xs: List[Int]) =>
xs.reverse.reverse shouldBe xs
}
}
}Генераторы
ScalaCheck автоматически предоставляет генераторы Gen для встроенных типов. Можно также создавать пользовательские генераторы, например Gen.choose(1, 100) для целого числа из заданного диапазона.
import org.scalacheck.Gen
val smallInt: Gen[Int] = Gen.choose(1, 100)
val nonEmpty: Gen[List[Int]] = Gen.nonEmptyListOf(Gen.choose(0, 9))Использование пользовательского генератора
Передайте генератор в forAll, чтобы ограничить входные данные, например разрешить только положительные числа.
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
import org.scalacheck.Gen
class PosSpec extends AnyFlatSpec with Matchers with ScalaCheckPropertyChecks {
"abs" should "stay positive" in {
forAll(Gen.choose(1, 1000)) { (n: Int) =>
math.abs(n) should be > 0
}
}
}Уменьшение контрпримера
Если свойство не выполняется, ScalaCheck уменьшает ошибочные входные данные до наименьшего примера, для которого сбой всё ещё воспроизводится. Вместо огромного случайного списка Вы получаете минимальный контрпример, который легко отлаживать.
Условные свойства
Используйте whenever, чтобы ограничить свойство входными данными, удовлетворяющими предварительному условию. Входные данные, не удовлетворяющие условию, отбрасываются.
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should.Matchers
import org.scalatestplus.scalacheck.ScalaCheckPropertyChecks
class DivSpec extends AnyFlatSpec with Matchers with ScalaCheckPropertyChecks {
"division" should "hold for nonzero divisors" in {
forAll { (a: Int, b: Int) =>
whenever(b != 0) {
(a / b) * b + (a % b) shouldBe a
}
}
}
}Полезные свойства для проверки
Полезные категории свойств:
- Обратные преобразования: кодирование/декодирование, обращение/обращение.
- Инварианты: сортировка сохраняет длину.
- Алгебраические законы: коммутативность, ассоциативность, нейтральный элемент.
Когда это использовать
Тестирование свойств дополняет тесты на примерах, но не заменяет их. Используйте его для чистых функций с ясными математическими или структурными правилами. Для конкретных известных случаев и регрессий сохраняйте целевые тесты на примерах.
Быстрая проверка
Проверьте свои знания о тестировании на основе свойств.
Итоги
Вы изучили тестирование на основе свойств с помощью ScalaCheck:
- Формулируйте свойства, истинные для любых входных данных; фреймворк генерирует множество вариантов.
forAllуправляет генерацией, аGenсоздаёт пользовательские входные данные.wheneverдобавляет предварительные условия; ошибочные случаи уменьшаются до минимальных примеров.- Этот подход отлично подходит для обратных преобразований, инвариантов и алгебраических законов.
Изучай Scala с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 39
- Уроки
- 143
Часто задаваемые вопросы
Урок «Тестирование на основе свойств» бесплатный?
Да — полный текст урока «Тестирование на основе свойств» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Scala for Backend Engineering & Functional Programming, подпишись на CoddyKit PRO. Курс Scala for Backend Engineering & Functional Programming содержит 4 уроков всего.
Чему я научусь в уроке «Тестирование на основе свойств»?
ScalaCheck Ты практикуешь Scala for Backend Engineering & Functional Programming с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Scala for Backend Engineering & Functional Programming?
Предыдущий опыт не требуется. Scala for Backend Engineering & Functional Programming на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Тестирование на основе свойств»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Scala for Backend Engineering & Functional Programming?
Да. Каждый урок Scala for Backend Engineering & Functional Programming включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Стили ScalaTest
- Сопоставители
- Тестирование на основе свойств
- Моки и фикстуры