I have a strange bug in python code which only happens sometimes in CI.
We can't reproduce it.
Where is the test code:
response=self.admin_client.post(url, post)
self.assertEqual(200, response.status_code, response)
Sometimes we get a 302 which happens since the form gets saved.
My idea to debug this:
with some_magic_trace.trace() as trace:
response=self.admin_client.post(url, post)
self.assertEqual(200, response.status_code, trace)
The trace should contain the python lines (filename, line offset, line as string) executed by the interpreter.
How to implement some_magic_trace.trace()?
The trace module gives you a very simple solution (different from what you are asking for, but simple enough to have a try.)
from trace import Trace
tracer = Trace()
response = tracer.runfunc(self.admin_client.post, url, post)
self.assertEqual(200, response.status_code, response)
A more complex solution that entails creating a context manager that saves the trace and prints it only on exceptions, requires the use of sys.settrace. Just a template for your own implementation could be:
class MyTracer():
def __init__(self):
self.trace = None
def newscope(self, frame, event, arg):
## real work should be done here, just minimal example
self.trace.append((frame, event, arg))
return None
def pprint(self):
## real pretty printing of trace info should be done here
print(self.trace)
def __enter__(self):
self.trace = []
sys.settrace(self.newscope)
return self
def __exit__(self, exc_type, exc_val, exc_tb):
sys.settrace(None)
if exc_type is not None:
self.pprint()
## print some info gathered from exc_type, exc_val, exc_tb
Then you can:
with MyTracer():
response=self.admin_client.post(url, post)
self.assertEqual(200, response.status_code, response)
The idea is that a MyTracer instance has a tracer method newscope that saves some useful info in self.trace. On an abnormal exit from the context the pprint method is called; on a normal exit the trace info is discarded.
Most of the work has to be done in the tracing method newscope.
Some concrete examples of tracing functions can be found here.
To use trace.Trace with the with context instead of Trace.runfunc you can use:
import trace
class ContextTrace(trace.Trace):
def __enter__(self):
if not self.donothing:
sys.settrace(self.globaltrace)
return self
def __exit__(self,*others):
if not self.donothing:
sys.settrace(None)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With