2013-09-29 2 views
8

У меня есть простая функция, которая анализирует конфигурационный файл как JSON. Я хочу написать тест, который либо использует некоторые образцы статических файлов конфигурации, либо анализирует их, либо создает образцы во время теста и пытается их проанализировать.golang test temp directory

Это не совсем нужно вопрос, но здесь основной код:

// config.go 

// ...(package,imports)... 

// Overall settings - corresponds to main.conf 
type MainSettings struct { 
    // stuff 
} 

// Load main.conf from the specified file path 
func LoadMainSettings(path string) (*MainSettings, error) { 

    b, err := ioutil.ReadFile(path) 
    if err != nil { return nil, err } 

    r := &MainSettings{} 
    err = json.Unmarshal(b, r) 
    if err != nil { return nil, err } 

    return r, nil 

} 

и тест:

// config_test.go 

func TestLoadMainSettings(t *testing.T) { 

    // possibly generate some example config files, 
    // or use static samples packaged with the source 

    s, err := LoadMainSettings("conf/main.conf") // <-- what should this path be?? 
    if err != nil { panic(err) } 

    // more sanity checking... 

} 

Тем не менее, мои конкретные вопросы:

  • Есть ли место для статических активов (l ike примеры конфигурационных файлов), которые применимы только к тестам?
  • Во время выполнения теста есть правильная (кросс-платформа, очищается с местом «go clean») для записи временных файлов?

(Примечание: Я бегу большинство моих вещей на Linux для постановки и производства и Mac для местного разработчика - так что использование/TMP/как временный каталог для тестов работает для меня на практике, но было интересно, если есть. лучший способ ...)


EDIT: Законченное использование этого подхода для теста:

f, err := ioutil.TempFile("", "testmainconf") 
if err != nil { panic(err) } 
defer syscall.Unlink(f.Name()) 
ioutil.WriteFile(f.Name(), []byte("{...sample config data...}"), 0644) 

s, err := LoadMainSettings(f.Name()) 

но с другой предложением сделать LoadMainSettings принять io.Reader вместо string также является хорошей идеей.

+2

Вы можете написать свой тест, так он использует 'io.Reader' напрямую? Если это так, то ваш тестовый пример не будет зависеть от файловой системы, так как ваши тесты могут использовать 'strings.NewReader' для предоставления соответствующего тестового контента в самом тесте. – dyoo

+0

Хм - это интересная идея ... Немного более громоздка для вызывающего, но в остальном, да, это будет работать в этом случае. –

+1

Это не должно быть более громоздким для вызывающего. Файл * уже есть * io.Reader'. – MatrixFrog

ответ

8

Просто сравнить против того, что вы с ioutil.TempDir, вот что вещи выглядят как с io.Reader:

// Load main.conf from the specified file path 
func LoadMainSettings(src io.Reader) (*MainSettings, error) { 
    b, err := ioutil.ReadAll(src) 
    if err != nil { return nil, err } 

    r := &MainSettings{} 
    err = json.Unmarshal(b, r) 
    if err != nil { return nil, err } 

    return r, nil 
} 

В частности, мы изменяем аргумент из path строки в экземпляре srcio.Reader, и мы заменим ioutil.ReadFile с ioutil.ReadAll.

Тестовый пример, который вы написали, то в конечном итоге быть немного короче, именно потому, что мы можем обойтись без операций с файлами:

s, err := LoadMainSettings(strings.NewReader("{...sample config data...}")) 
+0

Правильно, имеет смысл на этом - для теста. Это также означает, что вызывающая программа в основной программе будет выполнять: f, err: = os.Open («conf/main.conf»);/* проверить ошибку открытия файла */defer f.close(); s, err: = LoadMainSettings (f); Если конфиги всегда читаются из файлов, и у меня есть несколько разных типов (LoadSomeOtherSettings(), LoadYetAnotherConfig() и т. Д.), Я думаю, что этот подход может быть не лучшим образом. Если мне не хватает чего-то ... –

+0

еще одна вещь: я полагаю, что сравниваю это с моим опытом работы с Java, где у вас обычно есть выходной каталог, созданный как часть выполнения набора JUnit, и он часто содержит не только результаты тестов, но временный каталог, в котором могут проходить тесты. И вы знаете, что когда «чистая» запускается на сборке, все будет уходить. Делает все просто. Было просто интересно, существует ли какая-то соответствующая концепция в этом, которая существует в go - но, как я вижу (и вы указываете), вероятно, лучше просто подойти к проблеме по-разному. –

+0

Yup. Временные файлы также прекрасны. Вы видите их в подкаталоге «testdata» таких пакетов, как http://golang.org/src/pkg/net/testdata/. Поэтому здесь нет жесткого правила: иногда имеет смысл иметь ваши тестовые данные в файлах, и иногда имеет смысл внедрять их в тесты. Как и в Java (где вы видите «java.io.InputStream» и «java.io.Reader» везде), вы увидите, что большинство кодов Go работает с общим «io.Reader», поэтому я просто хотел сделать что он был задокументирован как подход к вашему вопросу где-то. : P – dyoo

8

Вы можете использовать ioutil.TempDir или TempFile из той же упаковки.

+0

Прохладный - да, вот что я в итоге сделал. –

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