2016-10-29 4 views
4

Wie erstellt man In-Memory-Dateien für Unit-Tests in Go?In-Memory-Datei zum Testen

In Python teste ich das Lesen aus einer Datei oder das Schreiben in eine Datei mit io.BytesIO oder io.StringIO. Um zum Beispiel eine Datei-Parser zu testen, würde ich

def test_parse_function(): 
    infile = io.StringIO('''\ 
line1 
line2 
line3 
''') 
    parsed_contents = parse_function(infile) 
    expected_contents = ['line1', 'line2', 'line3'] # or whatever is appropriate 
    assert parsed_contents == expected_contents 

Ebenso für die Dateiausgabe haben, würde ich so etwas wie die folgenden haben:

def test_write_function(): 
    outfile = io.StringIO() 
    write_function(outfile, ['line1', 'line2', 'line3']) 
    outfile.seek(0) 
    output = outfile.read() 
    expected_output = '''\ 
line1 
line2 
line3 
''' 
    assert output == expected_output 

Antwort

9

können Sie einen Buffer verwenden.

Im Allgemeinen ist es eine gute Idee, io.Reader und io.Writer Schnittstellen in Ihrem Code zu verwenden (Puffer implementiert beide), um mit IO umzugehen. Auf diese Weise können Sie auf die gleiche Weise mit verschiedenen Eingabe-/Ausgabemethoden umgehen (lokale Datei, Speicherpuffer, Netzwerkverbindung ...), ohne zu wissen, mit welcher Funktion Sie gerade arbeiten. Es macht es abstrakter und macht das Testen trivial.


Beispiel für die Verwendung mit einer trivialen Funktion:

Funktionsdefinition:

// mypkg project mypkg.go 
package mypkg 

import (
    "bufio" 
    "io" 
    "strings" 
) 

func MyFunction(in io.Reader, out io.Writer) { 
    rd := bufio.NewReader(in) 
    str, _ := rd.ReadString('\n') 
    io.WriteString(out, strings.TrimSuffix(str, "\n")+" was input\n") 
} 

Funktion Gebrauch innerhalb eines Programms:

package main 

import (
    "mypkg" 
    "os" 
) 

func main() { 
    mypkg.MyFunction(os.Stdin, os.Stdout) 
} 

Test:

// mypkg project mypkg_test.go 
package mypkg 

import (
    "bytes" 
    "testing" 
) 

func TestMyFunction(t *testing.T) { 
    ibuf := bytes.NewBufferString("hello\n") 
    obuf := bytes.NewBufferString("") 
    MyFunction(ibuf, obuf) 
    if obuf.String() != "hello was input\n" { 
     t.Fail() 
    } 
} 
+0

Vielen Dank für die Bereitstellung der Codebeispiele! – gotgenes

2

Wie in "Pragmatic and Effective Testing in Go" erwähnt, können Sie spf13/afero für die Dateiabstraktion verwenden, was zu einfacheren Tests führt.

diese Bibliothek hat eine Using Afero for Testing:

Es gibt einen großen Vorteil ein Mock-Dateisystem zum Testen verwenden.

Es hat bei jeder Initialisierung einen vollständig leeren Zustand und kann unabhängig vom Betriebssystem leicht reproduziert werden.
Sie könnten Dateien nach Herzenslust erstellen und der Dateizugriff wäre schnell, während Sie auch vor all den lästigen Problemen mit dem Löschen temporärer Dateien, Windows-Dateisperrung usw. schützen.
Das MemMapFs-Backend ist perfekt zum Testen.

  • Viel schneller als die Durchführung I/O-Operationen auf dem Datenträger
  • vermeiden Sicherheitsprobleme und Berechtigungen
  • Weit mehr Kontrolle. 'rm -rf /' zuversichtlich
  • Testaufbau ist viel leichter zu tun
  • Kein Test Bereinigung erforderlich

Es verwendet eine fully atomic memory backed filesystem (MemMapFs).
Es ist vollständig gleichzeitig und wird innerhalb Go-Routinen sicher arbeiten.

+0

Afero verhöhnt ein ganzes Dateisystem. Das ist wirklich schwer im Vergleich zu meinen Bedürfnissen, wo ich nur Datei-I/O mocksen muss. Ich kann aber sehen, dass Afero für etwas wie Hugo einen Wert hat. – gotgenes