- Item 9: Set Yourself Up for Debugging Success
- Item 10: Enable the Efficient Reproduction of the Problem
- Item 11: Minimize the Turnaround Time from Your Changes to Their Result
- Item 12: Automate Complex Testing Scenarios
- Item 14: Consider Updating Your Software
- Item 15: Consult Third-Party Source Code for Insights on Its Use
- Item 16: Use Specialized Monitoring and Test Equipment
- Item 17: Increase the Prominence of a Failure's Effects
- Item 18: Enable the Debugging of Unwieldy Systems from Your Desk
- Item 19: Automate Debugging Tasks
- Item 20: Houseclean Before and After Debugging
- Item 21: Fix All Instances of a Problem Class
Item 12: Automate Complex Testing Scenarios
Automate complex scripting scenarios through the use of scripting. There are multiple options for this. For orchestrating processes and files, the Unix shell offers many useful facilities (see Item 22: “Analyze Debug Data with Unix Command-Line Tools”). In addition, with commands such as cURL to fetch URLs and jq to parse JSON data, you can also use the shell to test web services. In complex cases involving API access and state maintenance, you will benefit from a more sophisticated scripting language, such as Python, Ruby, or Perl. Also, numerous systems come with their own built-in scripting language; for example, the Apache HTTP Server, the Wireshark network packet analyzer, and the VLC media player all support the Lua programming language.
If your software does not support a scripting language and you have the ability to modify it, consider bolting a scripting language onto it, and add API bindings that expose the scripting language to your program’s functions. As a (simple but contrived) example, say you want to construct a test case associated with a math library you’ve implemented. The C program in Listing 2.1 will load and run the Lua program debug.lua, exposing to it the functions sin, cos, and tan.
Listing 2.1 Exporting C functions for testing through Lua
#include <math.h> #include "lua5.2/lua.h" #include "lua5.2/lauxlib.h" // Functions exposed to Lua static int l_sin(lua_State *L) { double value_as_number = luaL_checknumber(L, 1); // Call the function, and return the result lua_pushnumber(L, sin(value_as_number)); return 1; // Single result } static int l_cos(lua_State *L) { double value_as_number = luaL_checknumber(L, 1); lua_pushnumber(L, cos(value_as_number)); return 1; } static int l_tan(lua_State *L) { double value_as_number = luaL_checknumber(L, 1); lua_pushnumber(L, tan(value_as_number)); return 1; } int main() { // Setup Lua lua_State *L = luaL_newstate(); luaL_openlibs(L); // Expose the functions to Lua lua_pushcfunction(L, l_sin); lua_setglobal(L, "lsin"); lua_pushcfunction(L, l_cos); lua_setglobal(L, "lcos"); lua_pushcfunction(L, l_tan); lua_setglobal(L, "ltan"); // Load and run the debug file luaL_dofile(L, "debug.lua"); puts("Done"); return 0; }
On a Debian Linux distribution, I installed Lua by running sudo apt-get install lua5.2-dev and compiled the program with cc myprog.c-llua5.2-lm. (You can find advice on how to install Lua on other systems in Lua’s documentation.) I then wrote the following small Lua program to verify the accuracy of the functions with respect to the definition of the tangent function.
Figure 2.1 A representation of how a log file will look: in the default editor setup (top) and with a wide view (bottom)
First, maximize your display area. Many developers also use two (or more) high-resolution monitors. (Using large cheap TV screens won’t cut it, for they will just give you blurry characters.) For this to work, you’ll need a correspondingly powerful graphics interface. If you’re working on a laptop, you can connect an external monitor, extend (rather than clone) your display into it, and benefit from the increased screen real estate. In all these cases, don’t shy away from switching your editor or terminal window to full-screen mode. It may look silly on a modern full HD monitor, but for some tasks, being able to see the data along and across is an indispensable affordance. If the data still can’t fit, decrease the font size (and get a pair of glasses) or use a video projector.
Printing stuff can also be remarkably effective. At just 600-DPI resolution, a laser printer can display 6600 × 5100 pixels on a letter-size paper—many more than your monitor, which you can use to display more and crisper data. You can use printed sheets for items that don’t change a lot, such as data structure definitions and listings, and free up your screen to display the more dynamic parts of your debugging session. Finally, the best medium for program listings is surely the 15-inch green bar fanfold paper. There you can print 132-column-wide text of unlimited length. If you’ve still got access to a printer that can handle this, use it. And guard its existence.
Things to Remember
With a lot of data in view, you can concentrate better and spot patterns and correlations.
Use the largest display area you can obtain.
Display relatively static data on printed sheets.