Ich habe mehrere Funktionen zum Erstellen von Plots, die ich in Jupyter-Notizbüchern zur Visualisierung von Daten verwende.

Ich möchte grundlegende Tests für diese erstellen und überprüfen, ob sie weiterhin ausgeführt werden, ohne dass Fehler bei verschiedenen Eingaben auftreten, wenn ich Änderungen vornehme. Wenn ich diese Funktionen jedoch mit pytest aufrufe, bleibt das Programm beim Erstellen der Diagramme hängen, bis ich das Diagramm manuell minimiere.

import pytest 
import matplotlib.pyplot as plt 

def plot_fn():
    plt.plot([1,2,3])
    plt.show()


def test_plot_fn():
   plot_fn()

Wie kann ich testen, dass Funktionen wie 'plot_fn' ohne Fehler mit Pytest ausgeführt werden? Ich habe Folgendes versucht, aber es funktioniert nicht. Ich denke, weil plt.show () dazu führt, dass das Skript hängen bleibt und daher plt.close ('all') nicht erreicht.

def test_plot_fn():
   plot_fn()
   plt.close('all')

Ich ändere gerne das Verhalten meiner Plotfunktion, um beispielsweise das plt-Objekt zurückzugeben.

3
oli5679 8 Feb. 2020 im 16:19

3 Antworten

Beste Antwort

Das funktioniert.

from unittest.mock import patch 
import pytest 
import matplotlib.pyplot as plt 

def plot_fn():
    plt.plot([1,2,3])
    plt.show()

@patch("matplotlib.pyplot.show")
def test_plot_fn(mock_show):
    plot_fn()

Basierend auf dieser Antwort (mögliches Duplikat) Deaktivieren Sie Diagramme, während Sie Unittests ausführen

0
oli5679 8 Feb. 2020 im 14:35

Ich bin nicht sicher, wie matplotlib mit pytest interagiert, aber es scheint, als müssten Sie fixtures verwenden, um dies zu erreichen. Sie müssen in Ihrem Test auch eine Art assert -Anweisung erstellen, die signalisiert, dass der Test Ihr Gerät ordnungsgemäß herunterfährt. So etwas sollte die gewünschten Ergebnisse erzielen.

import pytest 
import matplotlib.pyplot as plt 

@pytest.fixture(scope='function')
def plot_fn():
    def _plot(points):
        plt.plot(points)
        yield plt.show()
        plt.close('all')
    return _plot


def test_plot_fn(plot_fn):
    points = [1, 2, 3]
    plot_fn(points)
    assert True

Wenn Sie einfach monkeypatch das show Verhalten möchten, würde ich es wie unten gezeigt tun.

def test_plot_fn(monkeypatch):
    monkeypatch.setattr(plt, 'show', lambda: None)
    plot_fn()
0
gold_cy 8 Feb. 2020 im 18:12

Ich kann über zwei Optionen nachdenken:

  1. Verwenden Sie die plt.show (block = False) und schließen Sie die Abbildung trotzdem, wenn der Test endet.

  2. Speichern Sie im Test anstelle von plt.show den Plot in einer Datei plt.savefig. Auf diese Weise können Sie die erstellte Datei auch mit einer Testreferenz vergleichen und testen, ob Ihr Plot identisch ist. Natürlich müssen Sie für diese Option Ihre Funktion durch optionale Parameter, env-Variablen usw. "wissen lassen", dass sie sich im Testmodus befindet.

0
Lior Cohen 8 Feb. 2020 im 13:32