blob: 0157d46ac2f5b516a141f19eb41ca4f64db9c9f9 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<org.eclipse.epf.uma:ContentDescription xmi:version="2.0"
xmlns:xmi="http://www.omg.org/XMI" xmlns:org.eclipse.epf.uma="http://www.eclipse.org/epf/uma/1.0.4/uma.ecore"
xmlns:epf="http://www.eclipse.org/epf" epf:version="1.2.0" xmi:id="-60dp5lxFJEpUarhchGCnHw"
name="test_ideas_for_statechart_and_flow_diagrams,1.0347051690476123E-305" guid="-60dp5lxFJEpUarhchGCnHw"
version="1.0.0">
<mainDescription>&lt;a id=&quot;XE_state_machine__test_ideas_for&quot; name=&quot;XE_state_machine__test_ideas_for&quot;>&lt;/a>&lt;a id=&quot;XE_test_idea__for_state_machine&quot; name=&quot;XE_test_idea__for_state_machine&quot;>&lt;/a> &#xD;
&lt;h3>&#xD;
&lt;a id=&quot;Introduction&quot; name=&quot;Introduction&quot;>Introduction&lt;/a>&#xD;
&lt;/h3>&#xD;
&lt;p>&#xD;
This guideline shows how to identify &lt;a class=&quot;elementLinkWithUserText&quot; href=&quot;./../../../xp/guidances/concepts/test-ideas_list.html#TestIdeas&quot; guid=&quot;8.834380241450745E-306&quot;>test ideas&lt;/a> from statecharts and other design structures that consist mainly of nodes&#xD;
connected by arcs and that show something of the possible control flows of a program. The main goal of this testing is&#xD;
to traverse every arc in some test. If you've never exercised an arc, why do you think it will work when a customer&#xD;
does?&#xD;
&lt;/p>&#xD;
&lt;h3>&#xD;
&lt;a id=&quot;Implementation&quot; name=&quot;Implementation&quot;>Testing the Implementation&lt;/a>&#xD;
&lt;/h3>&#xD;
&lt;p>&#xD;
Consider this statechart:&#xD;
&lt;/p>&#xD;
&lt;p align=&quot;center&quot;>&#xD;
&lt;img height=&quot;253&quot; alt=&quot;&quot; src=&quot;resources/tstfrsdsg-img3.gif&quot; width=&quot;567&quot; />&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;picturetext&quot;>&#xD;
Fig1: HVAC Statechart&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
Here's a first list of test ideas:&#xD;
&lt;/p>&#xD;
&lt;ul>&#xD;
&lt;li>&#xD;
Idle state receives Too Hot event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Idle state receives Too Cool event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Cooling/Startup state receives Compressor Running event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Cooling/Ready state receives Fan Running event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Cooling/Running state receives OK event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Cooling/Running state receives Failure event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Failure state receives Failure Cleared event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Heating state receives OK event&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Heating state receives Failure event&#xD;
&lt;/li>&#xD;
&lt;/ul>&#xD;
&lt;p>&#xD;
These test ideas could all be exercised in a single test, or you could create several tests that each exercise a few.&#xD;
As with all test design, strive for a balance between the ease of implementation of many simple tests and the&#xD;
additional defect-finding power of complex tests. (See &lt;a class=&quot;elementLinkWithUserText&quot; href=&quot;./../../../xp/guidances/concepts/test-ideas_list.html#TestDesignUsingTheList&quot; guid=&quot;8.834380241450745E-306&quot;>&quot;test design using the list&quot;&lt;/a> in the &lt;a class=&quot;elementLinkWithUserText&quot; href=&quot;./../../../xp/guidances/concepts/test-ideas_list.html&quot; guid=&quot;8.834380241450745E-306&quot;>Concept: Test Ideas List&lt;/a> page.) If you have use case scenarios that describe certain&#xD;
paths through the statechart, you should favor tests that take those paths.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
In any case, the tests should check that all actions required by the statechart actually take place. For example, is&#xD;
the alarm started on entry to the Failure state, then stopped upon exit?&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
The test should also check that the transition leads to the correct next state. That can be a difficult problem when&#xD;
the states are invisible from the outside. The only way to detect an incorrect state is to inject some sequence of&#xD;
events that leads to incorrect output. More precisely, you would need to construct a follow-on sequence of events whose&#xD;
externally-visible results for the &lt;i>correct&lt;/i> state differ from those that the same sequence would provoke from&#xD;
each possible &lt;i>incorrect&lt;/i> state.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
In the example above, how would you know that the Failure Cleared event in the Failure state correctly led to the Idle&#xD;
state, instead of staying in the Failure state? You might trust that the stopping of the Alarm meant that transition&#xD;
had been made, but it might be better to check by lowering the temperature enough to make the heater start or raising&#xD;
it enough to turn on cooling. If something happens, you're more confident that the transition was correct. If nothing&#xD;
happens, it's likely the device stayed in the Failure state.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
At the very least, determining whether the resulting state is correct complicates test design. It is often better to&#xD;
make the state machine explicit and make its states visible to the tests.&#xD;
&lt;/p>&#xD;
&lt;h4>&#xD;
Other statechart constructs&#xD;
&lt;/h4>&#xD;
&lt;p>&#xD;
Statecharts consist of more than arcs and arrows. Here is a list of statechart constructs and the effect they have on&#xD;
the test idea list.&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
Event actions, entry actions, and exit actions&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
These do not generate test ideas per se. Rather, the tests should check that the actions behave as specified. If the&#xD;
actions represent substantial programs, those programs must be tested. The test ideas for the programs might be&#xD;
combined with test ideas from the statechart, but it's probably more manageable to separate them. Make the decision&#xD;
based on the effort involved and on your suspicion that there might be interactions between events. That is, if a&#xD;
particular action on one arc cannot possibly share data with an action on another arc, there is no reason to exercise&#xD;
the two actions in the same test (as you would if they were part of the same path through a statechart test).&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
Guard conditions&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
Guard conditions are boolean expressions. The test ideas for guard conditions are derived as described in &lt;a class=&quot;elementLinkWithType&quot; href=&quot;./../../../xp/guidances/guidelines/test_ideas_for_booleans_and_boundaries.html&quot; guid=&quot;1.7150344523489172E-305&quot;>Guideline: Test Ideas for Booleans and Boundaries&lt;/a>.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
In the example above, the Too Cool transition from the Idle state is guarded with [restart time &amp;gt;= 5 mins]. That&#xD;
leads to two separate test ideas:&#xD;
&lt;/p>&#xD;
&lt;ul>&#xD;
&lt;li>&#xD;
Idle state receives Too Cool event when restart time is five minutes (transition taken)&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
Idle state receives Too Cool event when restart time is just less than five minutes (transition blocked)&#xD;
&lt;/li>&#xD;
&lt;/ul>&#xD;
&lt;p>&#xD;
In both cases, any test that uses the test idea should check that the correct state is reached.&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
Internal transitions&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
An internal transition adds the same sort of ideas to a test idea list as an external transition does. It's merely that&#xD;
the next state is the same as the original state. It would be prudent to set up the test such that the state's entry&#xD;
and exit actions would cause an observable effect if they were incorrectly triggered.&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
Nested states&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
When constructing tests, set them up such that entry and exit events of the composite state have observable effects.&#xD;
You want to notice if they're skipped.&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
Concurrent substates&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
Testing of concurrency falls outside of the scope of developer testing.&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
Deferred events&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
If you suspect an event might be handled differently depending on whether it was deferred and queued rather than&#xD;
generated while the program was actually in the receiving state, you might test those two cases.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
If the event in the receiving state has a guard condition, consider the ramifications of changes to the condition's&#xD;
variables between the time the event is generated and the time it is received.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
If more than one state can handle a deferred event, consider testing deferral to each of the possible receiving states.&#xD;
Perhaps the implementation assumes that the &quot;obvious&quot; state will handle the event.&#xD;
&lt;/p>&#xD;
&lt;h5>&#xD;
History states&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
Here is an example of a history state:&#xD;
&lt;/p>&#xD;
&lt;p align=&quot;center&quot;>&#xD;
&lt;img height=&quot;211&quot; alt=&quot;&quot; src=&quot;resources/md_state3.gif&quot; width=&quot;412&quot; />&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;picturetext&quot;>&#xD;
Fig2: History State Example&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
The transition into the history state represents three real transitions, and thus three test ideas:&#xD;
&lt;/p>&#xD;
&lt;ul>&#xD;
&lt;li>&#xD;
BackupUp event in Command state leads to Collecting state&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
BackupUp event in Command state leads to Copying state&#xD;
&lt;/li>&#xD;
&lt;li>&#xD;
BackupUp event in Command state leads to CleaningUp state&#xD;
&lt;/li>&#xD;
&lt;/ul>&#xD;
&lt;h5>&#xD;
Chain states&#xD;
&lt;/h5>&#xD;
&lt;p>&#xD;
Chain states do not seem to have any implications for test design, except that they introduce more actions that need to&#xD;
be checked.&#xD;
&lt;/p>&#xD;
&lt;h3>&#xD;
&lt;a id=&quot;Design&quot; name=&quot;Design&quot;>Testing the Design&lt;/a>&#xD;
&lt;/h3>&#xD;
&lt;p>&#xD;
The preceding discussion focuses on checking whether the implementation matches the design. But the design might also&#xD;
be wrong. While examining the design to find test ideas, also check for two types of problems:&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
&lt;b>Missing events.&lt;/b> The statechart shows a state's response to events &lt;i>that the designer anticipated could arrive&#xD;
in that state&lt;/i>. It's not unknown for designers to overlook events. For example, in this statechart (repeated from&#xD;
the top of the page), perhaps the designer forgot that a failure can occur in the Ready substate of Cooling, not just&#xD;
when the fan is Running.&#xD;
&lt;/p>&#xD;
&lt;p align=&quot;center&quot;>&#xD;
&lt;img height=&quot;253&quot; alt=&quot;&quot; src=&quot;resources/tstfrsdsg-img3.gif&quot; width=&quot;567&quot; />&#xD;
&lt;/p>&#xD;
&lt;p class=&quot;picturetext&quot;>&#xD;
Fig3: HVAC Statechart&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
For this reason, it's wise to ask, for each state, whether any of the events that apply to other states might apply to&#xD;
this one. If you discover that one does, correct your design.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
&lt;b>Incomplete or missing guard conditions.&lt;/b> Similarly, perhaps guard conditions on one transition will suggest guard&#xD;
conditions on others. For example, the above statechart takes care not to restart the heater too often, but there is no&#xD;
such restriction on the cooling system. Should there be?&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
It is also possible that variables used on one guard condition will suggest that other guard conditions are too simple.&#xD;
&lt;/p>&#xD;
&lt;h3>&#xD;
&lt;a id=&quot;Interactions&quot; name=&quot;Interactions&quot;>Testing Interactions&lt;/a>&#xD;
&lt;/h3>&#xD;
&lt;p>&#xD;
Testing each arc in a graph is by no means complete testing. For example, suppose the start state initializes a&#xD;
variable to 0, state Setter sets it to 5, and state Divider divides it into 100 (100/variable). If there's a path from&#xD;
the start state to Divider that does not pass through Setter, you have a divide-by-zero exception. If the statechart&#xD;
has many states, simply exercising each arc might miss that path.&#xD;
&lt;/p>&#xD;
&lt;p>&#xD;
Except for very simple statecharts, testing every path is infeasible. In practice, tests that are complex and&#xD;
correspond to use case scenarios are often sufficient. If you desire stronger tests, consider requiring a path from&#xD;
each state where a datum is given a value to each state that uses it.&#xD;
&lt;/p>&lt;br />&#xD;
&lt;br /></mainDescription>
</org.eclipse.epf.uma:ContentDescription>