Skip to content

Miscellaneous

Gerard Murphy edited this page May 18, 2014 · 10 revisions
  1. WithMaximumStrength is a method on a factory that imposes a local cap on its strength - so regardless of the overall strength used to generate test cases, this factory and (in the absence of further strength caps) its subtree will impose a limit on the strength passed down. Going deeper into the subtree gives lower-level caps a chance to limit the strength further - but it is never increased, rather the current strength is used as-is if it is less than the cap limit.

  2. WithZeroStrengthCost is a method on a factory that gives it a 'free-pass'; it can explore the combinations from its subtree right up to the limits of its strength without taking away from the strength of its sibling subtrees. The effect is to allow combinations of test variables that include test variables from the zero-cost subtree to have a higher strength than what was specified by the client (or via strength caps). However, the subset of test variables in these combinations that aren't in the zero-cost tree still obey the usual strength guarantee. It is possible to have more than one zero-cost sibling subtree. The best thing to do is to have a play with this and see what it does!

  3. Synthesis.Create has handy overloads that allow use WithZeroStrengthCost to create and / or apply a permutation across a list of test cases generated by the child factories. The choice of permutation is governed by an internal test variable added in by the implementation. Again, have a play around.

  4. Synthesis.CreateWithPermutation also generates permutations from an internal test variable - but instead of applying the permutation to the list of test cases from the child factories, it simply returns those test cases in a sequence along with a permutation delegate that can be used to permute that sequence, or the result of processing that sequence by applying a map or any other transformation that preserves the size of the sequence. You can see this in action in the Short Sample.

  5. Synthesis.Create has another overload that allows curried F# functions to be used for synthesis. It takes an instance of FixedCombinationOfFactoriesForSynthesis as an argument - the latter is built up from a SynthesisInputs and a curried F# function. The easiest way to understand how this works is to look at the test code in FactoryTests.fs - search inside and you find it in action.

  6. Did you know that you could make a synthesizing applicative functor / workflow that works with curried F# functions, if the option in point #5 is not to your taste? Pure is a singleton factory taking the curried function as its singleton value - apply is our friend Synthesis.Create (specifically, the overload taking a binary delegate and two factories to supply its child test cases). By chaining up syntheses on the left, one can progressively apply the curried function to a chain of test cases, resulting in a final test case. One for the functional programming crowd...

    PS: if you do this, why not contribute it to NTestCaseBuilder? :-)

  7. It's a good idea to study the tests for NTestCaseBuilder to see just what the Synthesis API can do, as well as browse the overloads.

  8. There are actually two public interfaces for factories - IFactory and ITypedFactory. These are analogous to IEnumerable and IEnumerable, and couple to the latter classes as well. Browse the interfaces and you'll get the idea.

  9. You can make an enumerable of test cases from the corresponding factory interface, if you want to decide how to process the test cases yourself. See CreateEnumerable in the interfaces IFactory and ITypedFactory.

  10. There is a dangerous, but handy, automatic filter modifier defined on factories - WithAutoFilter. The idea is to create a filter than automatically avoids creating test cases that would throw an exception on being constructed, but without worrying about what test variables need to take what test levels etc. Simply apply it to a factory and presto, that factory will have a filter than will suppress the creation of exceptional test cases. Great!

    The problem is that the implementation of NTestCaseBuilder has no idea about which particular combination of test variables and their levels gave rise to the exception - all it knows is that the entire complete test case it sees is bad - so the opportunity to selectively repack pieces of that test case is lost. At its worst, using an auto-filter at the top of a tree of factories is hardly any better than simply applying post-processing to throw away bad test cases - the only benefit is that the exception handling is hidden away (although that is actually quite handy in its own right).

To get the most benefit from auto filters, they need to applied as soon as possible deep down in the subtree of factories below the root factory - that way, there are more opportunities for NTestCaseBuilder to repack the overall test cases produced by the root factory. You have been warned!

  1. Finding it tedious to do the thinking about test variable indices required to write a filter for WithFilter on a factory? Scared to use WithAutoFilter because of what I wrote in point #10?

    You need to try the other overload of WithAutoFilter that takes a FilterUsingTaggedInputs. Look at FilterUsingTaggedInputs and the companion interface ITaggedFilterInputs and all will be revealed - specify test variables by specific factories in the subtree, rather than the factory the filter is applied to!

The gist of the idea is to tag factories belonging to the subtree of some factory you want to add a filter modifier to. The filter delegate can probe its input using a predicate that looks at the tags, picking out the factories that the filter is interested in. This results in a filter input partitioned by tag - so one knows which test variables belong to which tagged factories. The test variable indices within each partition calculated for the partition's tagged factory, so there is no fiddling around working out the test variable index from the point of view of the factory the filter was applied to. Much easier, especially if one just gets right down to the bottom of the factory tree and tags the test variable factories themselves. Try it!

Clone this wiki locally