我正在开发一个python (2.7)程序,它会生成许多不同的matplotlib图形(数据不是随机的)。我愿意实现一些测试(使用unittest),以确保生成的数据是正确的。例如,我将期望的图形(数据或图像)存储在某个位置,然后运行我的函数并将结果与引用进行比较。有没有办法做到这一点?
发布于 2015-01-15 03:32:30
在我的experience中,图像比较测试最终带来的麻烦比它们的价值更多。如果您希望跨多个可能具有稍微不同的字体或可用绘图后端的系统(如TravisCI)运行持续集成,情况尤其如此。即使在函数完全正常工作的情况下,保持测试通过也可能需要大量的工作。此外,这种测试方式需要将图像保存在git存储库中,如果您经常更改代码,这可能会很快导致存储库膨胀。
在我看来,更好的方法是(1)假设matplotlib实际上将正确地绘制图形,(2)对绘图函数返回的数据运行数值测试。(如果您知道在哪里查找,也可以始终在Axes
对象中找到此数据。)
例如,假设您想测试一个简单的函数,如下所示:
import numpy as np
import matplotlib.pyplot as plt
def plot_square(x, y):
y_squared = np.square(y)
return plt.plot(x, y_squared)
然后,您的单元测试可能如下所示
def test_plot_square1():
x, y = [0, 1, 2], [0, 1, 2]
line, = plot_square(x, y)
x_plot, y_plot = line.get_xydata().T
np.testing.assert_array_equal(y_plot, np.square(y))
或者,等同地,
def test_plot_square2():
f, ax = plt.subplots()
x, y = [0, 1, 2], [0, 1, 2]
plot_square(x, y)
x_plot, y_plot = ax.lines[0].get_xydata().T
np.testing.assert_array_equal(y_plot, np.square(y))
发布于 2019-02-17 00:45:23
您还可以使用unittest.mock模拟matplotlib.pyplot
,并检查是否使用适当的参数对其进行了适当的调用。假设您想要测试module.py
中的一个plot_data(data)
函数(假设它位于package/src/
中),该函数如下所示:
import matplotlib.pyplot as plt
def plot_data(x, y, title):
plt.figure()
plt.title(title)
plt.plot(x, y)
plt.show()
为了在test_module.py
文件中测试此函数,您需要:
import numpy as np
from unittest import mock
import package.src.module as my_module # Specify path to your module.py
@mock.patch("%s.my_module.plt" % __name__)
def test_module(mock_plt):
x = np.arange(0, 5, 0.1)
y = np.sin(x)
my_module.plot_data(x, y, "my title")
# Assert plt.title has been called with expected arg
mock_plt.title.assert_called_once_with("my title")
# Assert plt.figure got called
assert mock_plt.figure.called
这将检查是否使用参数my title
调用了title
方法,以及是否在plt
对象的plot_data
内调用了figure
方法。
更详细的解释:
@mock.patch("module.plt")
装饰器“修补”导入到module.py
中的plt
模块,并将其作为mock
对象(mock_plt
)作为参数注入到test_module
中。这个模拟对象(作为mock_plt
传递)现在可以在我们的测试中使用,以记录plot_data
(我们正在测试的函数)对plt
执行的所有操作-这是因为plot_data
对plt
的所有调用现在都将在我们的模拟对象上进行。
此外,除了assert_called_once_with之外,您可能还想使用其他类似的方法,如assert_not_called、assert_called_once等。
https://stackoverflow.com/questions/27948126
复制相似问题