Hallo,
ich bin gerade am Einsteigen und erproben von Test::Unit.
Hier mal ein Programmschnipsel wie ich es verwenden will. Kommentare über Sinn und Unsinn und wie ich es besser machen kann sind willkommen und erwünscht.
Zum Hintergrund:
Ich will Tests für einen Dokumentengenerierer aufbauen. Ich kann zwar Detailtests machen, bin aber schnell an dem Punkt wo es (IMHO) unsinnig wird.
Ein assert_equal ist zwar schön und gut für kurze Ergebnisse, aber ich habe teilweise längere Texte die ich prüfen will. Und bei Abweichungen muss ich ziemlich lange suchen, bis ich den Unterschied entdecke.
Und da mein Ziel sowieso die Dateierzeugung ist, dachte ich mir, ich Vergleiche mit Dateien.
Der Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
require 'test/unit' require 'ftools' class Test::Unit::TestCase # #Takes the content of the file 'filename' and compares it with 'actual' like in assert_equal. #If 'filname' doesn't exist, the failure # Reference file <#{filename}> missing #is returned. # #'folder_for_failure' will contain all results with differences. # #Recommendation to build up your test. #1) Create two folders: 'expected' and 'failure' #2) Define your assertion with a non-existing filename #3) Run the test with folder_for_failure = 'failure' #4) You will get a failure (filename is missing). #5) Copy the file in 'failure' to 'expected' #6) Rerun again, you hav no failure (hopefully ;-) ) def assert_equal_filecontent( filename, actual, folder_for_failure = nil, message = nil ) if File.exist?(filename) expected = File.readlines(filename).to_s full_message = build_message(message, "<?> expected (#{filename}) but was\n<?>.\n", expected, actual) else full_message = "Reference file <#{filename}> missing" end #Write the real result to a file. #Folder is defined with Test::Unit::TestCase#folder_for_failure if folder_for_failure and expected != actual File.makedirs(folder_for_failure) if ! File.directory?(folder_for_failure) File.open( "#{folder_for_failure}/#{File.basename(filename)}", 'w'){|f| f << actual } end assert_block( full_message ){ expected == actual } end # end
class MyTest < Test::Unit::TestCase def test_myblock() folder_for_failure = 'failure' assert_equal_filecontent( 'expected/test.yaml', ['aaa'].to_yaml, folder_for_failure ) assert_equal_filecontent( 'expected/test2.yaml', {1=> 'eins', 2 => 'zwei'}.to_yaml, folder_for_failure) end end |
Mein Vorgehen:
- Ich habe einen Ordner 'expected' in dem ich meine Referenzdokumente ablege.
- Jetzt baue ich meine assertions mit assert_equal_filecontent auf.
Dabei übergebe ich den Dateinamen meiner 'korrekten' Datei. - assert_equal_filecontent liest die Referenzdatei ein und vergleicht mit dem neu erzeugten Inhalt.
- Bei Abweichungen wird im Ordner 'failure' eine Datei mit den erzeugten Inhalt angelegt.
- Der Test meldet die Abweichung und ich kann mit einem diff die Dateien vergleichen.
Je nach Ergebnis kann ich mein Programm anpassen bis der Inhalt passt, oder ich übernehme die Datei im failure-Ordner als neue Referenz.
Beim Ordner zum speichern der Abweichung bin ich noch nicht ganz glücklich. Da bin ich noch am überlegen, ob ich die nicht einmal zentral definieren soll.
Evtl. brauche ich später noch ein assert_similar_filecontent, in dem ich zusätzliche Regeln einbaue, wann zwei Files identisch sind (z.B. Zeitstempel entfernen)