Suivre l'exemple à https://golang.org/pkg/os/ Exec / # cmd.stdoutpipe , supposons que j'ai une fonction dans mon application "vraie", la commande La course peut avoir des sorties différentes, j'aimerais écrire des cas de test pour chacun de ces scénarios. Cependant, je ne sais pas comment y aller. P> Jusqu'à présent, tout ce que j'ai est un cas de test pour un cas: p> peut-être le Un moyen d'y aller consiste à diviser cette fonction en deux parties, qui écrit la sortie de la commande à une chaîne et une autre qui décode la sortie d'une chaîne? p> p> getperson () code> défini comme:
3 Réponses :
J'ai ajouté des tests de l'unité en divisant la fonction en deux parties: une qui lit la sortie à une tranche d'octets, et celle qui analyse la sortie à une personne Les cas de test suivants passent: p> où le code>:
Bob code> et
alice code> Les cas de test simulent une sortie différente qui peut être généré par la commande. p> p>
ajouter à https://stackoverflow.com/a/58107208/9353289 ,
au lieu d'écrire séparément Fonctions de test pour chaque test, je vous suggère d'utiliser une approche de test basée sur la table à la place. Voici un exemple, P>
func Test_getPerson(t *testing.T) { tests := []struct { name string commandOutput []byte want Person }{ { name: "Get Bob", commandOutput: []byte(`{"Name": "Bob", "Age": 32}`), want: Person{ Name: "Bob", Age: 32, }, }, { name: "Get Alice", commandOutput: []byte(`{"Name": "Alice", "Age": 25}`), want: Person{ Name: "Alice", Age: 25, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := getPerson(tt.commandOutput) require.NoError(t, err) assert.Equal(t, tt.want.Name, got.Name) assert.Equal(t, tt.want.Age, got.Age) }) } }
Votre conception de mise en œuvre rejette activement les tests de grain précis, car il ne permet aucune injection.
Cependant, étant donné l'exemple, en plus d'utiliser une testtable, il n'y a pas beaucoup à améliorer. P>
maintenant, sur Une nouvelle charge de travail, vous pourriez rencontrer des cotisations de ralentissement inacceptables à appeler au binaire externe. Cela pourrait justifier une autre approche impliquant un refactoring de conception à la moqueur et la configuration de plusieurs talons de tests. P>
Pour se moquer de votre implémentation, vous utilisez des fonctionnalités code> code>. Pour supprimer votre exécution, vous créez une simule qui sortit que vous souhaitez rechercher. P>
package main import ( "encoding/json" "fmt" "os/exec" ) type Person struct{} type PersonProvider struct { Cmd outer } func (p PersonProvider) Get() (Person, error) { person := Person{} b, err := p.Cmd.Out() if err != nil { return person, err } err = json.Unmarshal(b, &person) return person, err } type outer interface{ Out() ([]byte, error) } type echo struct { input string } func (e echo) Out() ([]byte, error) { cmd := exec.Command("echo", "-n", e.input) return cmd.Output() } type mockEcho struct { output []byte err error } func (m mockEcho) Out() ([]byte, error) { return m.output, m.err } func main() { fmt.Println(PersonProvider{Cmd: echo{input: `{"Name": "Bob", "Age": 32}`}}.Get()) fmt.Println(PersonProvider{Cmd: mockEcho{output: nil, err: fmt.Errorf("invalid json")}}.Get()) }