Many system failures don't show up until the system is operated at or near its boundary conditions; this is the motivation behind testing techniques such as boundary-value analysis and domain analysis for example. Let's see how we can apply model-based specification to our chemical tank use case, identifying the preconditions that specify when a system can be operated safely at its boundaries and conversely when we can expect failures to occur. Step 1. Identify Postconditions Associated with Boundaries of OperationIn the previous section, boundaries were identified on the rate of flow in and out of the chemical tank: Now we need to identify those postconditions that modify these variables and therefore have the potential of pushing the system beyond its specified bounds; in our chemical tank example, we have identified these two: Step 2. State an Invariant the Postconditions Should Not ViolateIn a model-based specification, when you define the boundaries on an initial state variable (unprimed)in testing this is called the domain of the variableit applies not only to the initial form of the variable (i.e., InFlow and OutFlow) but also to the primed versions as well, InFlow', InFlow" and OutFlow'. The domain definition of a variable is an invariant in its own right, one that is said to be true for all versions of the variable, primed and unprimed, in any scenario of the use case. What this means is that these boundary definitions: also imply these, which we take as invariants that we want to assure never fail: Step 3. Calculate PreconditionsWe want to determine what additional preconditionsif anyare needed to prevent the postconditions of Step 1 from causing the invariants of Step 2 to fail. But what did I mean by if any? When calculating preconditions, there are four possible outcomes:
The boundary statements stated earlier work out to be six separate precondition calculations: three boundary statements (InFlow', InFlow", and OutFlow') with each requiring one calculation for the lower bound, and one for the upper bound. As it turns out, of the six calculated preconditions, five are either implied or equal to existing preconditions. For brevity's sake, we won't do those calculations here. But one boundary does, in fact, identify a failure scenario, and we calculate the precondition needed to guard against it in Figure 5.13. Figure 5.13. Calculating precondition to guard invariant InFlow' MaxFlow.The failure scenario we have identified is this: If at the start of the use case, the flow out of the tank is running at maximum (i.e., OutFlow = MaxFlow), it will not be possible to increase the flow into the tank high enough to start refilling the tank without setting InFlow' to a value higher than MaxFlow, the upper bound on safe rate of flow in and out of the tank. The precondition states the use case can only be expected to work if OutFlow is less than maximum when the use case starts. As we have already established Delta > 0, we know OutFlow will be less than the maximum in the precondition. Notice also that this precondition is a stronger constraint than the original domain definition (i.e., the new precondition OutFlow implies the domain definition condition of OutFlow stronger condition and the latter the weaker. In effect, the stronger overrides the weaker. |