This article covers the “Tracing Executions” chapter from The Debugging Book. In this article we will summarize the chapter and discuss how its content could be utilized within the context of the implementation and testing of the Chasten and Cellveyor tools.
This chapter in The Debugging Book talked about
Tracer and it’s capabilities to monitor and show how a function behaviors and what are its inputs and outputs.
Tracer allows you to observe many features of a program as it runs such as gives you access to see the current line number, variables, and more without having to write out numerous print statements using the command
sys.settrace. This command gives us the ability to trace everything and makes it very simple to the user.
frame argument holds the function and its local variables, working in this fashion:
frame.f_lineno: the current line
frame.f_locals: the current variables, as a Python dictionary
frame.f_code: the current code, as a
Codeobject, with attributes such as
frame.f_code.co_name, or the name of the current function
def traceit(frame: FrameType, event: str, arg: Any) -> Optional[Callable]:
print(event, frame.f_lineno, frame.f_code.co_name, frame.f_locals)
The aforementioned function traces the input program and prints out the event, which tells us what happens in the program line by line. The
trace function returns the most important values of the function.
The tracing function as well can be applied in a class and can work the same as before but on a much more expansive scale. This may improve the efficiency of a program and can easily work and perform the
trace function. The typical usage of
Tracer though in a class is done using the
with command. This would trace everything indented within the
with and everything that is not indented inside of the
with is not subject to tracing.
Tracing can also log while making sure the specific conditional expression does not get changed. The conditional tracer gets a conditional expression to be checked during executions. But only if this condition holds will it list the current status. You can use this for many different expressions and will only get the lines executed that are true to a statement.
After reading this chapter, we have a better understanding of what tracing entails. We have learned that there are several different ways to trace, from simply using the
settrace() function to writing a complex
Tracer class with conditional logic. We learned about frames and all the different variables within them. We learned how tracing can help improve the efficiency of the debugging process. With this knowledge, we can better understand the process of tracing and be able to implement tracing into our own programs.
After reading the article, our focus is on refining debugging by emphasizing the cause-and-effect chain, enhancing test case development, and integrating the scientific method. This approach proves beneficial in diagnosing and resolving bugs, fostering a methodical and systematic debugging process. Documentation practices will be updated, and a commitment to continuous learning will be realized through training programs. These actions aim to empower our team with a robust methodology, drawn from the insights of this chapter, enhancing our ability to debug code effectively because we will have more insights into a program’s behavior.