CIS 542 Embedded Systems Programming – Summer 2013 Lecture ...

CIS 542 Embedded Systems Programming – Summer 2013 Lecture ... CIS 542 Embedded Systems Programming – Summer 2013 Lecture ...

cis.upenn.edu
from cis.upenn.edu More from this publisher
28.02.2014 Views

We've already seen how to make sure that it progresses to the right state, but now we also want to check that it correctly updates the speed. Obviously, the solution here is testing. Testing is the activity of giving input to the code to see how it behaves. The goal of testing is not to show that it is correct, but rather to show that there are bugs (or faults, as we say). Broadly speaking, there are two ways to create test cases for a piece of code: • Black-box testing: look at the specification and come up with inputs that exercise as much of the spec as possible, i.e. try all the different conditions that are described • White-box testing: look at the code and come up with inputs that exercise as many statements/paths/branches as possible, i.e. try all the code Let's start with black-box testing. Consider this part of the spec: “if the driver chooses to accelerate, the speed increases by 10, unless that would put the speed over 100, in which case it doesn't change” There are two conditions here that we'd want to check: 1. the driver chooses to accelerate, but that doesn't put the speed over 100 2. the driver chooses to accelerate, and that does put the speed over 100 For each of these, we make the assumption that if it works correctly for some input, it will also work correctly for “similar” inputs. This is known as equivalence partitioning. For instance, if we decide to use 20 as the speed for #1, and it works correctly, we probably don't need to also test 21, 22, 30, 40, 80, etc. So we can now create some test code like this: /* this tests accelerating but not going over 100 */ int curr_speed = 20; enum events event = accel; enum states curr_state = moving; int new_speed = control(curr_speed, event, &curr_state); if (new_speed != 30) printf(“control returned wrong speed!\n”); if (curr_state != moving) printf(“control returned wrong state!\n”); /* this tests accelerating but trying to go over 100 */ curr_speed = 95; event = accel; curr_state = moving; new_speed = control(curr_speed, event, &curr_state); if (new_speed != 95) printf(“control returned wrong speed!\n”); if (curr_state != moving) printf(“control returned wrong state!\n”);

Because programmers often make off-by-one errors, we also want to include test cases that what happens when values are very close to the boundary between different parts of the spec. These are known as boundary conditions. In this case, it would be if we try to accelerate and the speed becomes exactly 100. /* this tests accelerating but and going exactly 100 */ curr_speed = 90; event = accel; curr_state = moving; new_speed = control(curr_speed, event, &curr_state); if (new_speed != 100) printf(“control returned wrong speed!\n”); if (curr_state != moving) printf(“control returned wrong state!\n”); What about white-box testing? In this approach to identifying test cases, we pick a particular statement, path, or branch, and then come up with inputs that cause it to be executed. For instance, if we wanted to cover the statement (line 20) in which we switch the state to “stopped”, then we'd have to figure out the inputs that would get us there. Clearly, we need: • *state == moving, so that we go to line 9 in the outer switch statement • event == brake, so that we go to line 16 in the inner switch statement • new_speed

Because programmers often make off-by-one errors, we also want to include test cases that what<br />

happens when values are very close to the boundary between different parts of the spec. These are<br />

known as boundary conditions. In this case, it would be if we try to accelerate and the speed becomes<br />

exactly 100.<br />

/* this tests accelerating but and going exactly 100 */<br />

curr_speed = 90;<br />

event = accel;<br />

curr_state = moving;<br />

new_speed = control(curr_speed, event, &curr_state);<br />

if (new_speed != 100)<br />

printf(“control returned wrong speed!\n”);<br />

if (curr_state != moving)<br />

printf(“control returned wrong state!\n”);<br />

What about white-box testing? In this approach to identifying test cases, we pick a particular statement,<br />

path, or branch, and then come up with inputs that cause it to be executed.<br />

For instance, if we wanted to cover the statement (line 20) in which we switch the state to “stopped”,<br />

then we'd have to figure out the inputs that would get us there. Clearly, we need:<br />

• *state == moving, so that we go to line 9 in the outer switch statement<br />

• event == brake, so that we go to line 16 in the inner switch statement<br />

• new_speed

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!