Если вы используете FsCheck, то вы можете использовать функцию Gen.filter
и функцию Gen.map
.
Допустим, у вас есть проверяемая функция funToBeTested
, которая требует, чтобы let funToBeTested a b = if a < b then a + b else failwith "a should be less than b"
И вы тестируете свойство, которое funToBeTested
пропорционально входным данным:
let propertyTested a b = funToBeTested a b / 2. = funToBeTested (a / 2.) (b / 2.)
У вас также есть предикат, который проверяет требования к условию для a & b:
let predicate a b = a > 0.0 && a < 1.0 && b > a
Мы начинаем с генерации float
чисел, используя Gen.choose
и Gen.map
, таким образом уже создаются значения только от 0,0 до 1,0:
let genFloatFrom0To1 = Gen.choose (0, 10000) |> Gen.map (fun i -> float i / 10000.0 )
Затем мы генерируем two
плавает от 0 до 1 и filter
, используя функцию predicate
выше
let genAB = Gen.two genFloatFrom0To1 |> Gen.filter (fun (a,b) -> predicate a b )
Теперь нам нужно создать новый тип TestData
для использования этих значений:
type TestData = TestData of float * float
и мы сопоставляем полученное значение с TestData
let genTest = genAB |> Gen.map TestData
Далее нам нужно зарегистрировать genTest
как генератор для TestData
, для этого мы создаем новый класс со статическим членом типаArbitrary<TestData>
:
type MyGenerators =
static member TestData : Arbitrary<TestData> = genTest |> Arb.fromGen
Arb.register<MyGenerators>() |> ignore
наконец мы проверяем свойство, используя TestData
в качестве ввода:
Check.Quick (fun (TestData(a, b)) -> propertyTested a b )
ОБНОВЛЕНИЕ:
Простой способ составления различных генераторов - это использование gen
Выражения вычислений:
type TestData = {
a : float
b : float
c : float
n : int
}
let genTest = gen {
let! a = genFloatFrom0To1
let! b = genFloatFrom0To1
let! c = genFloatFrom0To1
let! n = Gen.choose(0, 30)
return {
a = a
b = b
c = c
n = n
}
}
type MyGenerator =
static member TestData : Arbitrary<TestData> = genTest |> Arb.fromGen
Arb.register<MyGenerator>() |> ignore
let ``Test rate Calc`` a b c n =
let r = rCalc a b c
(float) r >= 0.0 && (float) r <= 1.0
Check.Quick (fun (testData:TestData) ->
``Test rate Calc``
testData.a
testData.b
testData.c
testData.n)