0
votes

Comment tester une fonction Go qui exécute une commande?

Suivre l'exemple à https://golang.org/pkg/os/ Exec / # cmd.stdoutpipe , supposons que j'ai une fonction getperson () défini comme: xxx

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.

Jusqu'à présent, tout ce que j'ai est un cas de test pour un cas: xxx

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?


0 commentaires

3 Réponses :


0
votes

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 : xxx

Les cas de test suivants passent: xxx

où le Bob et alice Les cas de test simulent une sortie différente qui peut être généré par la commande.


0 commentaires

2
votes

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)

        })
    }
}


0 commentaires

0
votes

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())

}


0 commentaires