Должен ли я повторно реализовать логику в тесте на основе свойств?

Допустим, есть функция, определяющая, должна ли кнопка быть видимой.

fun isButtonVisible(fitlers: List<Filters>, results: List<Shop>, isLoading: Boolean) {
  return fitlers.isNotEmpty() && results.isEmpty() && !isLoading
}

Теперь я хотел бы протестировать эту функцию с помощью PBT, например:

"the button should be visible if filters is not empty and results is empty and is not loading" {
  forAll { filters: List<Filters>, results: List<Shop>, isLoading: Boolean ->
    val actual = isButtonVisible(filters, results, isLoading)

    // Here reimplement the logic
    val expected = filters.isNotEmpty() && results.isEmpty() && !isLoading

    assertThat(actual).isEqual(expected)
  }
}

Кажется, я просто снова реализую логику в своем тесте, это правильно? Если нет, как я могу придумать другие свойства, если логика состоит из простых комбинаций нескольких флагов?


person jaychang0917    schedule 02.06.2019    source источник
comment
Вы можете переделать, но я не предлагаю. Вместо этого вы должны обработать результат и жестко запрограммировать его. Итак, assertThat(actual).isEqual(true) если это должно быть правдой.   -  person CodingYoshi    schedule 02.06.2019
comment
Можете ли вы привести пример? В этом случае я понятия не имею, какие еще свойства я могу использовать, кроме его повторной реализации.   -  person jaychang0917    schedule 02.06.2019
comment
Я уже приводил пример. Я не уверен, что вы спрашиваете.   -  person CodingYoshi    schedule 02.06.2019
comment
обработайте результат и жестко закодируйте его ‹ - вы имеете в виду, что я должен использовать тест, основанный на примерах, для жесткого кода 8 возможных случаев? Если да, то почему это лучше, чем повторная реализация? Не лучше ли в этом случае ПБТ, если комбинаций много?   -  person jaychang0917    schedule 03.06.2019
comment
то каждая комбинация становится отдельным испытанием   -  person Andrei Dragotoniu    schedule 03.06.2019
comment
Это лучше, чем повторная реализация, потому что в некоторых случаях реализация очень сложна, поэтому повторная реализация может содержать ошибки. Вам не нужно 8 разных тестов; посмотрите на параметризованные тесты.   -  person CodingYoshi    schedule 03.06.2019


Ответы (1)


это неправильно.

вам не нужно вычислять ожидаемое значение во время теста, вы должны знать, каким должен быть результат, установить его как таковой и сравнить с фактическим результатом.

Тесты работают, вызывая метод, который вы хотите протестировать, и сравнивая результат с уже известным ожидаемым значением.

"the button should be visible when filters are not empty, results is empty, isLoading is false " {
  forAll { filters: List<Filters>, results: List<Shop>, isLoading: Boolean ->
    val actualVisibleFlag = isButtonVisible(filters, results, isLoading)

    val expectedVisibleFlag = true    
    assertThat(actualVisibleFlag ).isEqual(expectedVisibleFlag )
  }
}

Ваше ожидаемое значение известно, это то, что я пытаюсь сделать. Для каждой комбинации входных данных вы создаете новый тест.

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

Если вы вызываете метод, чтобы получить результат, который, по вашему мнению, вы должны получить, ну, откуда вы знаете, что этот метод в любом случае правильный? Откуда вы знаете, что он работает правильно для каждой комбинации?

Вам может сойти с рук меньшее количество тестов, если вы уменьшите количество флагов, может быть, вам действительно нужно 4 из них?

Теперь каждый язык/фреймворк имеет (или должен иметь) поддержку матричных вещей, поэтому вы можете легко записывать значения каждой комбинации.

person Andrei Dragotoniu    schedule 03.06.2019
comment
Но как насчет того, что если мой isButtonVisible вычисляется по 4 флагам, то мне нужно жестко кодировать все 16 тестовых случаев? Значит, нет других лучших вариантов? - person jaychang0917; 03.06.2019
comment
добавил немного больше - person Andrei Dragotoniu; 03.06.2019