Technologieaustausch

Machen Sie Unit-Tests

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

In der Go-Sprache werden Unit-Tests über das Testpaket in der Standardbibliothek implementiert, das eine Reihe von Funktionen bereitstellt, die das Schreiben, Ausführen und Verwalten von Unit-Tests einfach und effizient machen.

1. Regeln

  • Benennungsregeln für Dateien testen
    Die Benennungsregel für Testdateien in Go besteht darin, hinzuzufügen_test.go .Wenn Sie beispielsweise eine habencalculator.go Datei sollte die entsprechende Testdatei seincalculator_test.go

  • Benennungsregeln für Testfunktionen
    Die Testfunktion muss mit beginnenTest beginnt und kann beispielsweise von einer beliebigen nicht leeren Zeichenfolge gefolgt werdenTestAddTestSubtract Warten.

  • verwenden testing.T Machen Sie Aussagen und melden Sie Fehler
    Verwenden Sie in der Testfunktiontesting.T Geben Sie Parameter ein, um den Teststatus und die Ausgabe zu verwalten.Sie können verwendent.Error*t.Fail* und andere Methoden, um Testfehler anzuzeigen und relevante Fehlerinformationen auszugeben.

2. Unit-Test-Beispiel

2.1 Einzelner Testfall

Im Rechnerpaket ist eine Rechnerfunktion definiert. Die spezifische Implementierung lautet wie folgt:

package calculator

func Add(a, b int) int {
	return a + b
}
  • 1
  • 2
  • 3
  • 4
  • 5

Im aktuellen Verzeichnis erstellen wir eine Testdatei rechner_test.go und definieren eine Testfunktion wie folgt:

package calculator

import "testing"


func TestAdd(t *testing.T) {
	result := Add(1, 2)
	expected := 3
	if result != expected {
		t.Errorf("Add(1,2) return %d, expected %d", result, expected)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Um diesen Komponententest auszuführen, verwenden Sie den Befehl go test.Geben Sie in der Befehlszeile das Verzeichnis mit Rechner.go und Rechner_test.go ein und führen Sie es dann ausgo test, diese Ergebnisse sind wie folgt

go test
PASS
ok      modu    0.226s
  • 1
  • 2
  • 3

2.2 Mehrere Testfälle

Fügen Sie die folgende Testfunktion in Rechner_test.go hinzu:

func TestAdd2(t *testing.T) {
	result := Add(3, 2)
	expected := 3
	if result != expected {
		t.Errorf("Add(1,2) return %d, expected %d", result, expected)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Um die Ausführung jedes Testfalls in den Ausgabeergebnissen besser sehen zu können, können wir dies tungo test -vParameter, damit vollständige Testergebnisse ausgegeben werden können.

go test -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
=== RUN   TestAdd2
    calculator_test.go:17: Add(1,2) return 5, expected 3
--- FAIL: TestAdd2 (0.00s)
FAIL
exit status 1
FAIL    modu    0.216s
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

2.3 Geben Sie laufende Testfälle an

go test -run Der Befehl kann Tests gemäß dem angegebenen Modus ausführen. Dieser Befehl unterstützt reguläre Ausdrücke zur Auswahl der auszuführenden Testfunktionen.

Bestehen Sie beispielsweise nach der Korrektur des TestAdd2-Anwendungsfallsgo tes -run=Add2Führen Sie nur den TestAdd2-Testfall aus. Das Ergebnis ist

go test -run=Add2 -v
=== RUN   TestAdd2
--- PASS: TestAdd2 (0.00s)
PASS
ok      modu    0.198s
  • 1
  • 2
  • 3
  • 4
  • 5

4. Überspringen Sie einige Testfälle
Neue Testfunktion hinzufügen

func TestAdd3(t *testing.T) {
	if testing.Short() {
        t.Skip("short模式下会跳过该测试用例")
    }
	
	result := Add(3, 2)
	expected := 5
	if result != expected {
		t.Errorf("Add(1,2) return %d, expected %d", result, expected)
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

bei der Ausführunggo test -shorWenn t, wird es übersprungentesting.Short()Der markierte Testfall ist das Ergebnis

go test -short -v
=== RUN   TestAdd
--- PASS: TestAdd (0.00s)
=== RUN   TestAdd2
--- PASS: TestAdd2 (0.00s)
=== RUN   TestAdd3
    calculator_test.go:23: short模式下会跳过该测试用例
--- SKIP: TestAdd3 (0.00s)
PASS
ok      modu    0.635s
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3. Testgruppen und Untertests

3.1 Testgruppen und Untertests

Durch Testgruppen und Untertests können Sie weitere Testfälle hinzufügen und die Ergebnisse benutzerfreundlicher anzeigen

func TestAdd(t *testing.T) {
	tests := []struct {
		name     string
		x, y     int
		expected int
	}{
		{"Add1", 1, 2, 3},
		{"Add2", 3, 3, 6},
		{"Add3", 4, 5, 8},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			result := Add(tc.x, tc.y)
			if result != tc.expected {
				t.Errorf("Add(%d, %d) returned %d, expected %d", tc.x, tc.y, result, tc.expected)
			}
		})
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

laufengo test -v,sich herausstellen

go test -v
=== RUN   TestAdd
=== RUN   TestAdd/Add2
=== RUN   TestAdd/Add3
    calculator_test.go:51: Add(4, 5) returned 9, expected 8
--- FAIL: TestAdd (0.00s)
    --- PASS: TestAdd/Add1 (0.00s)
    --- PASS: TestAdd/Add2 (0.00s)
    --- FAIL: TestAdd/Add3 (0.00s)
FAIL
exit status 1
FAIL    modu    0.190s
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3.2 Paralleles Testen

Die Go-Sprache unterstützt von Natur aus Parallelität, also durch Hinzufügent.Parallel()Um eine Parallelisierung von Treibertests zu erreichen.

func TestAdd(t *testing.T) {
	t.Parallel()  // 将 TLog 标记为能够与其他测试并行运行
	// 这里使用匿名结构体定义了若干个测试用例
	// 并且为每个测试用例设置了一个名称
	tests := []struct {
		name     string
		x, y     int
		expected int
	}{
		{"Add1", 1, 2, 3},
		{"Add2", 3, 3, 6},
		{"Add3", 4, 5, 8},
	}

	for _, tc := range tests {
		tc := tc  // 注意这里重新声明tt变量(避免多个goroutine中使用了相同的变量)
		t.Run(tc.name, func(t *testing.T) {
			t.Parallel()  // 将每个测试用例标记为能够彼此并行运行
			result := Add(tc.x, tc.y)
			if result != tc.expected {
				t.Errorf("Add(%d, %d) returned %d, expected %d", tc.x, tc.y, result, tc.expected)
			}
		})
	}
}
  • 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

3.3 Testabdeckung

verwendengo test -coverum die Testabdeckung anzuzeigen

go test -cover
PASS
        modu    coverage: 100.0% of statements
ok      modu    1.149s
  • 1
  • 2
  • 3
  • 4

4. Gehen Sie zum Unit-Testing-Toolkit – geben Sie Zeugnis

Da bei der Durchführung von Unit-Tests in der Go-Sprache die offizielle Assertionsfunktion nicht integriert ist, müssen wir normalerweise eine große Anzahl davon verwendenif...else... Erklärung zur Überprüfung der Testergebnisse.Durch die Verwendung von Bibliotheken von Drittanbietern wie ztestify/assertkönnen wir problemlos eine Vielzahl häufig verwendeter Assertionsfunktionen aufrufen, die nicht nur den Testcode vereinfachen, sondern auch klare und leicht verständliche Fehlerbeschreibungsinformationen generieren, die uns helfen, das Problem schnell zu lokalisieren.

Im obigen Beispiel verwenden wirif...else...Erklärung zur Überprüfung der Testergebnisse

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			result := Add(tc.x, tc.y)
			if result != tc.expected {
				t.Errorf("Add(%d, %d) returned %d, expected %d", tc.x, tc.y, result, tc.expected)
			}
		})
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

Jetzt verfügbartestify/assertDer obige Beurteilungsprozess wird wie folgt vereinfacht:

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			result := Add(tc.x, tc.y)
			assert.Equal(t, result, tc.expected)
		})
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

testify/requirehabentestify/assertAlle Behauptungsfunktionen, der einzige Unterschied zwischen ihnen isttestify/requireWenn ein fehlgeschlagener Testfall auftritt, wird der Test sofort abgebrochen.