2016-08-02 3 views
4

У меня есть следующий код: Golangтест блока отличается флаг значения

func getConfigFile() string { 
    var configFile string 
    flag.StringVar(&configFile, "config", "", "File containing configuration") 
    flag.Parse() 
    return configFile 
} 

Эта функция используется в другом месте в моем коде, и я хотел бы модульного тестирования, что здесь происходит, когда пользователь предоставляет различные значения config (имя файла конфигурации используется else где).
Есть ли способ сообщить пакету флага вернуть разные значения для аргумента конфигурации во время тестирования?

+4

Нет, нет. Просто разделите свою функцию на a) разбор флагов, который не тестируется на устройствах и b) загрузка файлов конфигурации – Volker

ответ

0

Если вы измените его, как код ниже, go test потерпит неудачу, но go test -config testconfig пройдет. Не то, чтобы нам не нужно было звонить flag.Parse() в init(), так как он вызывается тестовым пакетом (как упоминает Роб Пайк в https://groups.google.com/d/msg/golang-nuts/uSFM8jG7yn4/PIQfEWOZx4EJ).

package main 

import (
    "flag" 
    "testing" 
) 

var configFile = flag.String("config", "", "File containing configuration") 

func getConfigFile() string { 
    return *configFile 
} 

func TestConfig(t *testing.T) { 
    want := "testconfig" 
    if s := getConfigFile(); s != want { 
     t.Errorf("Got %s, want %s", s, want) 
    } 
} 

Тест работает:

$ go test 
--- FAIL: TestConfig (0.00s) 
    flag_test.go:17: Got , want testconfig 
FAIL 
exit status 1 
FAIL github.com/dmitris/soflagtest 0.013s 
$ go test -config testconfig 
PASS 
ok  github.com/dmitris/soflagtest 0.012s 

Вы можете также использовать var configFile string декларации и init() функцию, чтобы присвоить значение флага переменные:

func init() { 
    flag.StringVar(&configFile, "config", "", "File containing configuration") 
} 

(то никакого указателя не разыменование в getConfigFile, поскольку configFile является строкой)

1

Я обнаружил, что для проверки пользовательских флагов лучше создать собственный набор флагов, таким образом, я могу полностью протестировать флаги, включая опцию -h, не выходя из тестов. надеюсь, что прилагается код может дать вам и о том, как вы могли бы реализовать тест на код:

package main 

import (
    "flag" 
    "fmt" 
    "os" 
    "reflect" 
    "testing" 
) 

// Test Helper 
func expect(t *testing.T, a interface{}, b interface{}) { 
    if a != b { 
     t.Errorf("Expected: %v (type %v) Got: %v (type %v)", a, reflect.TypeOf(a), b, reflect.TypeOf(b)) 
    } 
} 

type Flags struct { 
    ConfigFile string 
} 

func (self *Flags) Parse(fs *flag.FlagSet) (*Flags, error) { 
    fs.StringVar(&self.ConfigFile, "config", "", "File containing configuration") 

    err := fs.Parse(os.Args[1:]) 
    if err != nil { 
     return nil, err 
    } 

    return self, nil 
} 

func main() { 

    fs := flag.NewFlagSet("test", flag.ContinueOnError) 

    parser := Flags{} 
    flags, err := parser.Parse(fs) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Println(flags) 

} 

func TestFlags(t *testing.T) { 
    oldArgs := os.Args 
    defer func() { os.Args = oldArgs }() 
    var flagTest = []struct { 
     flag  []string 
     name  string 
     expected interface{} 
    }{ 
     {[]string{"cmd", "-config", "config.yaml"}, "ConfigFile", "config.yaml"}, 
     {[]string{"cmd", "-config", "config.json"}, "ConfigFile", "config.json"}, 
     {[]string{"cmd", "-v"}, "Version", true}, 
    } 

    for _, f := range flagTest { 
     os.Args = f.flag 
     p := &Flags{} 
     fs := flag.NewFlagSet("test", flag.ContinueOnError) 

     flags, err := p.Parse(fs) 
     if err != nil { 
      t.Error(err) 
     } 

     refValue := reflect.ValueOf(flags).Elem().FieldByName(f.name) 
     switch refValue.Kind() { 
     case reflect.Bool: 
      expect(t, f.expected, refValue.Bool()) 
     case reflect.String: 
      expect(t, f.expected, refValue.String()) 
     } 
    } 

} 

Я положил его и здесь: https://play.golang.org/p/h1nok1UMLA надеюсь, что это может дать вам идею.

Смежные вопросы