Мне больше нравится @DariusV решение. Однако это плохо работает, когда я, разработчик, запускаю тестовый метод непосредственно из боковой панели Xcode. Это нарушение сделки для меня.
То, что я закончил делать, я думаю, довольно гладко.
Я объявляю Dictionary
из testValues
(возможно, для этого нужно лучшее имя) как вычисляемое свойство экземпляра моего подкласса XCTestCase
. Затем я определяю Dictionary
литерал входных данных, обозначающих ожидаемые выходные данные. В моем примере проверяется функция, которая воздействует на Int
, поэтому я определяю testValues
так:
static var testRange: ClosedRange<Int> { 0...100 }
var testValues: [Int: Int] {
let range = Self.testRange
return [
// Lower extreme
Int.min: range.lowerBound,
// Lower bound
range.lowerBound - 1: range.lowerBound,
range.lowerBound : range.lowerBound,
range.lowerBound + 1: range.lowerBound + 1,
// Middle
25: 25,
50: 50,
75: 75,
// Upper bound
range.upperBound - 1: range.upperBound - 1,
range.upperBound : range.upperBound,
range.upperBound + 1: range.upperBound,
// Upper extreme
Int.max: range.upperBound
]
}
Здесь я очень легко объявляю свои крайние и граничные случаи. Более семантический способ сделать то же самое может заключаться в использовании массива кортежей, но литеральный синтаксис словаря Swift достаточно тонкий, и я знаю, что он делает. ????
Теперь в моем тестовом методе есть простой цикл for
.
/// The property wrapper I'm testing. This could be anything, but this works for example.
@Clamped(testRange) var number = 50
func testClamping() {
let initial = number
for (input, expected) in testValues {
// Call the code I'm testing. (Computed properties act on assignment)
number = input
XCTAssertEqual(number, expected, "{number = \(input)}: `number` should be \(expected)")
// Reset after each iteration.
number = initial
}
}
Теперь, чтобы запустить для каждого параметра, я просто вызываю XCTests любым из обычных способов Xcode или любым другим способом, который работает с Linux (я полагаю). Нет необходимости запускать каждый тестовый класс, чтобы получить параметризованность этого.
Разве это не красиво? Я только что рассмотрел каждое граничное значение и класс эквивалентности всего в нескольких строках кода DRY!
Что касается определения неудачных случаев, каждый вызов проходит через функцию XCTAssert
, которая, согласно соглашению Xcode, будет выдавать вам сообщение только в том случае, если что-то не так, о чем вам нужно подумать. Они отображаются на боковой панели, но похожие сообщения имеют тенденцию смешиваться друг с другом. Моя строка сообщения здесь идентифицирует ошибочный ввод и его результирующий вывод, исправляя смешивание вместе и превращая мой поток тестирования в нормальный кусок вишневого яблочного пирога. (Ты можешь отформатировать свой как угодно, деревенщина! Все, что благословит твое здравомыслие.)
Вкусные.
TL;DR
Адаптация @Code Different ответ: используйте словарь входных и выходных данных и выполните цикл for
. ????
person
AverageHelper
schedule
10.02.2020