Re: How did you learn your debugging skills?
From: Phlip (phlip_cpp_at_yahoo.com)
Date: 06/28/04
- Next message: Phlip: "Re: How did you learn your debugging skills?"
- Previous message: Phlip: "Re: How did you learn your debugging skills?"
- In reply to: Willem: "Re: How did you learn your debugging skills?"
- Next in thread: Dan Tex1: "Re: How did you learn your debugging skills?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Mon, 28 Jun 2004 14:40:14 GMT
Willem wrote:
> Nonsense, not all bugs crash a program or fail a test. Lots of bugs only
> become apparent when very specific conditions arise. Very specific input,
> usually.
>
> I have a very gut-feel approach to bugs, but my usual approach is to add
> trace points in the program, and use them to narrow down where the bug is.
> You can usually trace it to one function pretty quickly. Then, you have
an
> input to the function that produces bad output, it's like a puzzle to
> figure out how that output gets generated, and when you find that, you've
> usually found the bug.
I leverage the debugger, elaborate temporary trace statements, and a
technique I call Spigot, to capture legacy bugs with tests.
Treat I/O Like a Spigot
A common manual debugging technique is a temporary trace statement, such as
a quicky print statement. When you write one in a function with curious
behavior, run the program to it, see its output, then comment it out, you
treated that print like a little tiny hose. Data stream thru it, and
programmers have a knob in the source code to turn the stream off and on.
A window controlled by a Test Case is the same kind of thing - a simple I/O
port.
Most GUI Toolkits, as an optimization, can manipulate a window without
displaying it. So, at any time, any test can command its window to display,
in any state. This provides instant, temporary, visual confirmation that
things work.
print statements are easier to toggle on and off, because fewer bits flow
thru them than flow thru windows. Deal.
Different Toolkit types fight back in various ways, so remember the goal:
When the spigot is off, the Toolkit is Just Another Library. But when it's
on, you should instantly see one Test Case's window. Turning an existing
print trace statement on should be as easy as de-commenting it. Turning a
window on should be as easy as passing "true" to the Test Fixture that hosts
the window-the fixture that usually suppresses it.
Begin all GUI projects by locating or writing the Test Fixture that
temporarily displays tested windows. Each fixture should take care of all
application-specific environmental mechanics needed to instantly see the
window. A fixture could, for example, place image files into temporary
folders, then change the current directory to those folders, for the window
to find them as it displays. Put another way, turning a Spigot on must
require no extra thinking.
If you change a window's logic or esthetics, or if you write a new assertion
that Queries Visual State and need to see if the window matches the
assertion, turn on the spigot, and hit The Test Button. You will receive
instant visual feedback. If your test populates that window with sample
data, you will see it. If you Set a new esthetic control configuration, you
should be able to predict how different the window will now look.
If your Spigot Fixture takes care of all environmental details, you don't
need to pause, or think about technical details other than your most recent
change, and how you expect the window to look.
Authoring uses small cycles (edit/check/edit/check) for the same reason TDD
uses small cycles. We want to make the smallest change possible between
checks. If viewing the result were difficult, we might procrastinate until
we made enough changes to make viewing them worth the effort. If we must run
our main application thru a long series of actions to arrive at the window
under development, we won't check the window in that state very often. Then
we won't know which change broke something. Worse, the mighty Undo button
might be incapable of instantly fixing the problem, whatever it was. So,
because our test rig can put any window into any state, decoupled from our
main application, borrow the test rig's abilities to enable authoring.
Popping up a window should assist Flow, and should not interfere with
subsequent tests or programming.
The Spigot Fixture must support the other TFUI Principles by interacting
correctly with their code and environmental details.
----8<-----------------------
About the "very specific conditions" bugs, refactoring code to separate its
concerns tends to improve its bug resistance. When it does not, TDD at least
frees time in your schedule to aggressively manually test. When a sequence
of events uncovers a bug, writing a test case on the bug's module which
reproduces that sequence of inputs will be easy. If the first few attempts
to reproduce the bug in a test case fail, one can instrument the module with
trace statements, run the module manually into the bug condition, collect
the trace statement outputs, and use them for the input data to the test
case.
But, nowadays, I never get caught without tests on every module, so in the
rare event that a richochet hits my foot, it can't do much damage.
-- Phlip http://industrialxp.org/community/bin/view/Main/TestFirstUserInterfaces
- Next message: Phlip: "Re: How did you learn your debugging skills?"
- Previous message: Phlip: "Re: How did you learn your debugging skills?"
- In reply to: Willem: "Re: How did you learn your debugging skills?"
- Next in thread: Dan Tex1: "Re: How did you learn your debugging skills?"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]