8

I am testing out my module using the unittest library. This includes plotting some graphs using the matplotlib library. The issue at the moment is that the testing pauses every time a graph is plotted, and it only resumes after I close the graph. How can I avoid this?

bluprince13
  • 4,607
  • 12
  • 44
  • 91

3 Answers3

13

I will model my answer after the simple example code from the matplotlib tutorial: http://matplotlib.org/users/pyplot_tutorial.html

Let's assume we have the following module, plot_graph.py to be tested:

import matplotlib.pyplot as plt

def func_plot():
    plt.plot([1,2,3,4])
    plt.ylabel('some numbers')
    plt.show()

if __name__ == "__main__":
    func_plot()

The calls to show can be patched as follows:

from plot_graph import func_plot
from unittest.mock import patch

@patch("plot_graph.plt.show")
def test_plot(mock_show):
    assert func_plot() == None

As you can see, you should patch the calls to pyplot.show(). You can find more about patching and mocking in the docs: https://docs.python.org/3/library/unittest.mock.html.

Usually the section about where to patch is really useful: https://docs.python.org/3/library/unittest.mock.html#where-to-patch

Finally there are similar question already on the site: How to run nosetests without showing of my matplotlib's graph?

Community
  • 1
  • 1
Enrique Saez
  • 2,504
  • 16
  • 21
1

Don't call pyplot.show() if this is done in the tests. Also the documentation suggests using an experimental block=False keyword argument to the show function.

Lukisn
  • 190
  • 8
1

Just for completeness, I ran into a similar issue, but to fix it I had to mock out calls to matplotlib.pyplot.figure instead. I realize this isn't exactly what was asked, but this took me a while to figure out after coming across this thread, so I wanted to post it here.

If, for instance, your plot_graph.py looked like this:

import matplotlib.pyplot as plt

def func_plot():
    fig = plt.figure()
    plt.plot([1,2,3,4])
    plt.ylabel('some numbers')
    plt.show()

then, at least in my case (running unit tests on a terminal that has no X11 forwarding and errors out when it tries to open a plot), I needed the following in test_plot_graph.py to run my test:

from plot_graph import func_plot
from unittest.mock import patch

# unittest boilerplate...

@patch('matplotlib.pyplot.figure')
def test_func_plot(self, mock_fig):
    # whatever tests I want...
    mock_fig.assert_called()  # some assertion on the mock object
Engineero
  • 12,340
  • 5
  • 53
  • 75