Whenever possible,
instead of managing dependencies,
I work very hard
to eliminate them,
or at least reduce them.
Another high priority goal for me
is to eliminate any technology that is not directly involved
in the feature I'm testing.
Every additional element of technology
offers possibilities
for the tests to fail
independent of whether the system implements the feature correctly.
For through-the-UI tests,
I like to have each test use the GUI
only for GUI feature the test is testing.
Think of a test in three rough parts:
- Set up preconditions
- Invoke the feature being tested.
- Verify the results produced by the system.
If my test is testing that the feature can be invoked through the GUI,
then I'll go through the GUI to invoke the feature.
But I will skip around the GUI
to set up the preconditions
and verify the results.
I'll call some lower level API,
or stuff data into the database,
or something.
If my test is testing that the system displays
specific results in some specific way
through the GUI,
then I'll go through the GUI to verify the results.
But I will skip around the GUI
to set up the preconditions
and invoke the feature.
And if my test is not testing anything specifically about the GUI,
I will eliminate the GUI from the test altogether,
and make API calls into the system.
Further,
when I am testing GUI stuff,
I like to eliminate the system.
Instead, provide a mock system
that I can control directly
with my test code.
Then my test verifies that when the user fiddles with some widget,
the GUI makes the right API call.
Or it verifies that when the system gives a response,
the GUI displays it correctly
(to the limited extent that can be verified with automation).
I like to have very few
end-to-end automated tests.
Just enough to discover whether
the parts are wired together correctly.
For more complex things
like following data through the system,
have people do the tests.
People are much less sensitive to minor technology burps
that would cause an automated end-to-end test
to fail inadvertently.