Example #1
0
 public void CheckLerping <Q> (Func <Q, Q, float, Q> lerpFunc)
     where Q : struct, IQuat <Q, float>
 {
     (from quat1 in Prop.ForAll <Q> ()
      from quat2 in Prop.ForAll <Q> ()
      from alpha in Prop.Any(Gen.ChooseDouble(0.0, 1.0).ToFloat())
      let lerp = lerpFunc(quat1, quat2, alpha)
                 let len = lerp.Length
                           select new { quat1, quat2, alpha, lerp, len })
     .Check(p => p.lerp.IsNormalized,
            label: $"{typeof (Q).Name}: | lerp (quat1, quat2) | = 1");
 }
Example #2
0
        /*
         * You should now see your checks pass and the names are now a bit easier
         * to decipher.
         * ```
         * 'Count increased by one.' passed 100 tests. Discarded: 0
         * 'First item is the added item.' passed 100 tests. Discarded: 0
         * 'Rest of the sequence is same as the original.' passed 100 tests. Discarded: 0
         * 'Count increased by one.' passed 100 tests. Discarded: 0
         * 'First item is the added item.' passed 100 tests. Discarded: 0
         * 'Rest of the sequence is same as the original.' passed 100 tests. Discarded: 0
         * 00:00:00.0283599 - TestAddition
         * ```
         *
         ## Testing Removal
         ##The last feature we test is removing an item.
         */
        public void CheckRemoval <T> ()
        {
            /*
             * Let's again generate an arbitrary sequence and make sure it is not
             * empty. This time we use the `SuchThat` combinator defined for the
             * `IArbitrary` interface, which filters out all the randomly generated
             * values that do not match a given predicate. This has the benefit
             * that no test cases are discarded, but it also makes the test run
             * a bit longer. Also, if the predicate is too strict, `SuchThat`
             * might not find a suitable value. In this case the generator will
             * fail and throw an exception.
             */
            (from seq in Prop.ForAll(ArbitrarySeq <T> ().SuchThat(
                                         s => !s.IsEmpty()))

             /*
              * Next we need to select from the sequence an arbitrary item that we
              * can remove. We do this by calling `Prop.Any`. It differs from
              * `Prop.ForAll` in that it takes `Gen<T>` as an argument instead
              * of `IArbitrary<T>`. This means that the random values generated
              * by `Any` are not shrunk, if the test fails.
              *
              * Also, the values produced by `Any` might depend on the other
              * generated values. As in this case, the chosen element must be
              * inside the sequence that we generated previously. It would not
              * make sense to shrink this value, because then we would probably
              * loose the failing test case.
              *
              * In general, we need to make sure that the same input data
              * provides always the same result, and that our test case is
              * deterministic. Given the same parameters, `Any` produces always
              * the same result, whereas `ForAll` will produce a different value
              * every time it is called.
              */
             from item in Prop.Any(Gen.ElementOf(seq))

             /*
              * Now we can remove the chosen item.
              */
             let newSeq = seq.Remove(item)

                          /*
                           ### Classifying Test Cases
                           ###As a last step we return the test case. This time, however,
                           ###we use the `orderby` clause to classify our test cases by the
                           ###length of the sequence. By adding this clause we get a report
                           ###with the results of how many test cases we have with the specified
                           ###property. The report helps us determine, for example, if we have
                           ###enough test coverage for longer sequences.
                           */
                          orderby seq.Count()
                          select new { seq, item, newSeq })

            /*
             * Next we define some properties related to the removal operation.
             * We check that the new sequence should be one item shorter than the
             * original one.
             */
            .Check(t => t.newSeq.IsEmpty().Implies(t.seq.Count() == 1) ||
                   t.newSeq.Count() == t.seq.Count() - 1)

            /*
             ### Changing the Size of the Generated Data
             ###Before the second check let's use the `Restrict` combinator to make
             ###the test range a bit bigger. The combinator either widens our
             ###narrows our	test set. The default test "size" is 10, which means
             ###that we don't get sequences longer than 9 items. Effectively, we
             ###double our test range by setting the size to 20.
             ###
             ###The second property says that if we find the same item that was
             ###removed in the new sequence, it must be a duplicate, and thus
             ###appear at least twice.
             */
            .Restrict(20)
            .Check(t => !t.newSeq.Contains(t.item) ||
                   t.seq.Count(i => i.Equals(t.item)) > 1);
        }