Am einfachsten ist es, die Ausgabedatei zu schreiben, dann ihren Inhalt zu lesen, den Inhalt der (erwarteten) Golddatei zu lesen und sie mit der einfachen Zeichenfolgengleichheit zu vergleichen. Wenn sie identisch sind, löschen Sie die Ausgabedatei. Wenn sie unterschiedlich sind, erheben Sie eine Behauptung.
Auf diese Weise wird nach Abschluss der Tests jeder fehlgeschlagene Test mit einer Ausgabedatei dargestellt, und Sie können ein Drittanbieter-Tool verwenden, um sie von den Golddateien zu unterscheiden (Beyond Compare ist hierfür hervorragend geeignet).
Wenn Sie wirklich Ihre eigene Diff-Ausgabe bereitstellen möchten, denken Sie daran, dass die Python-Standardlib das Difflib-Modul enthält. Die neue unittest-Unterstützung in Python 3.1 enthält eine assertMultiLineEqual
Methode, mit der Unterschiede angezeigt werden, ähnlich wie folgt:
def assertMultiLineEqual(self, first, second, msg=None):
"""Assert that two multi-line strings are equal.
If they aren't, show a nice diff.
"""
self.assertTrue(isinstance(first, str),
'First argument is not a string')
self.assertTrue(isinstance(second, str),
'Second argument is not a string')
if first != second:
message = ''.join(difflib.ndiff(first.splitlines(True),
second.splitlines(True)))
if msg:
message += " : " + msg
self.fail("Multi-line strings are unequal:\n" + message)
import filecmp
Dann
quelle
shallow
Vergleich mit den Kontrollen nur die Dateien Metadaten (mtime, Größe usw.). Bitte fügen Sieshallow=False
in Ihrem Beispiel hinzu.Ich versuche immer zu vermeiden, Dateien auf die Festplatte zu schreiben, auch wenn es sich um einen temporären Ordner handelt, der meinen Tests gewidmet ist: Wenn Sie die Festplatte nicht berühren, werden Ihre Tests viel schneller, insbesondere wenn Sie häufig mit Dateien in Ihrem Code interagieren.
Angenommen, Sie haben diese "erstaunliche" Software in einer Datei namens
main.py
:""" main.py """ def write_to_file(text): with open("output.txt", "w") as h: h.write(text) if __name__ == "__main__": write_to_file("Every great dream begins with a dreamer.")
Um die
write_to_file
Methode zu testen , können Sie so etwas in eine Datei im selben Ordner schreiben, der heißttest_main.py
:""" test_main.py """ from unittest.mock import patch, mock_open import main def test_do_stuff_with_file(): open_mock = mock_open() with patch("main.open", open_mock, create=True): main.write_to_file("test-data") open_mock.assert_called_with("output.txt", "w") open_mock.return_value.write.assert_called_once_with("test-data")
quelle
Sie können die Inhaltsgenerierung von der Dateiverwaltung trennen. Auf diese Weise können Sie testen, ob der Inhalt korrekt ist, ohne mit temporären Dateien herumspielen und diese anschließend bereinigen zu müssen.
Wenn Sie eine Generatormethode schreiben , die jede Inhaltszeile liefert, können Sie eine Dateibehandlungsmethode verwenden, die eine Datei öffnet und
file.writelines()
mit der Zeilenfolge aufruft . Die beiden Methoden könnten sich sogar in derselben Klasse befinden: Testcode würde den Generator aufrufen, und Produktionscode würde den Dateihandler aufrufen.Hier ist ein Beispiel, das alle drei Testmöglichkeiten zeigt. Normalerweise wählen Sie nur eine aus, je nachdem, welche Methoden für die zu testende Klasse verfügbar sind.
import os from io import StringIO from unittest.case import TestCase class Foo(object): def save_content(self, filename): with open(filename, 'w') as f: self.write_content(f) def write_content(self, f): f.writelines(self.generate_content()) def generate_content(self): for i in range(3): yield u"line {}\n".format(i) class FooTest(TestCase): def test_generate(self): expected_lines = ['line 0\n', 'line 1\n', 'line 2\n'] foo = Foo() lines = list(foo.generate_content()) self.assertEqual(expected_lines, lines) def test_write(self): expected_text = u"""\ line 0 line 1 line 2 """ f = StringIO() foo = Foo() foo.write_content(f) self.assertEqual(expected_text, f.getvalue()) def test_save(self): expected_text = u"""\ line 0 line 1 line 2 """ foo = Foo() filename = 'foo_test.txt' try: foo.save_content(filename) with open(filename, 'rU') as f: text = f.read() finally: os.remove(filename) self.assertEqual(expected_text, text)
quelle
Aufgrund von Vorschlägen habe ich Folgendes getan.
class MyTestCase(unittest.TestCase): def assertFilesEqual(self, first, second, msg=None): first_f = open(first) first_str = first_f.read() second_f = open(second) second_str = second_f.read() first_f.close() second_f.close() if first_str != second_str: first_lines = first_str.splitlines(True) second_lines = second_str.splitlines(True) delta = difflib.unified_diff(first_lines, second_lines, fromfile=first, tofile=second) message = ''.join(delta) if msg: message += " : " + msg self.fail("Multi-line strings are unequal:\n" + message)
Ich habe eine Unterklasse MyTestCase erstellt, da ich viele Funktionen habe, die Dateien lesen / schreiben müssen, sodass ich wirklich eine wiederverwendbare Assert-Methode haben muss. In meinen Tests würde ich MyTestCase anstelle von unittest.TestCase unterordnen.
Was denkst du darüber?
quelle