This is not super likely, but still possible.
Approach two: plt.
gcfLuckily, matplotlib has another interface we can use to get around these shortcomings of patch: plt.
gcf() (get current figure).
I’m not sure if this is how Jupyter’s inline plotting magic works, but it’s mighty useful.
gcf returns a reference to the current (last plotted) figure.
Better yet, it includes a number (plt.
number) which lets you keep track of how many were plotted.
We can inspect the current figure after our plotting code is run to make whatever level of assertions we want on it.
So it doesn’t care if plt.
show was called, and works as long as somewhere the figures got created, even some higher-level library that internally uses matplotlib.
When I first found gcf, it was tempting to “reset” the plot number before calling the code to try and assert what the number of the current figure should be exactly.
I tried to “clear” the plot before doing so, with plt.
However, when I pushed to Travis the ‘close’ didn’t seem to do anything and the value of gcf().
number was affected by other test cases.
I assume this has to do with my laptop having an actual display/window and Travis being headless.
Maybe there’s a better way to do the ‘clearing’, but I wasn’t about to get into the weeds with displays, so instead I came up with an alternate way to make it deterministic:assert that the number of figures is higher than when you started the testThis works the same on Travis as on my laptop.
Another difference is that I’m not asserting a specific number of figures plotted.
Whether or not you want to do this in your code (ultimately I think it may get too deeply into how matplotlib is handling things internally), you could using this method.
But this by itself is a handy plot assertion tool.
I even ended up making it into a context manager-aware method for easy reuse:What are the possible shortcomings of this method?We’re asserting that whatever code we are calling to plot creates matplotlib figures.
Is this brittle?.Theoretically.
It definitely sounds like it violates the “don’t test the implementation” guideline.
But in all reality, I think thatmatplotlib is a common backend that many nice frontends that i may switch between will useis a safer assumption thanseaborn is the best frontend and i will always use it and maybe it will switch backends away from matplotlibMy team redoing a chart into a new, non-matplotlib-backed plotting library is certainly possible, but not very likely.
So I’m fairly comfortable with this as a reasonably-generic Python data visualization assertion.
What do you think?.Are there other shortcomings I’m missing, or better ways to test Python plotting?.. More details