testing Go में os.exit परिदृश्य का परीक्षण कैसे करें




exit-code (4)

एंड्रयू गेर्रेंड (गो टीम के मुख्य सदस्यों में से एक) की एक प्रस्तुति है जहां वह दिखाती है कि यह कैसे करना है।

फ़ंक्शन को देखते हुए ( main.go )

package main

import (
    "fmt"
    "os"
)

func Crasher() {
    fmt.Println("Going down in flames!")
    os.Exit(1)
}

यहां बताया गया है कि आप इसे कैसे परीक्षा देंगे ( main_test.go माध्यम से):

package main

import (
    "os"
    "os/exec"
    "testing"
)

func TestCrasher(t *testing.T) {
    if os.Getenv("BE_CRASHER") == "1" {
        Crasher()
        return
    }
    cmd := exec.Command(os.Args[0], "-test.run=TestCrasher")
    cmd.Env = append(os.Environ(), "BE_CRASHER=1")
    err := cmd.Run()
    if e, ok := err.(*exec.ExitError); ok && !e.Success() {
        return
    }
    t.Fatalf("process ran with err %v, want exit status 1", err)
}

कोड क्या करता है, एक अलग प्रक्रिया में exec.Command माध्यम से go test फिर से go test exec.Command , परीक्षण TestCrasher परीक्षण (- -test.run=TestCrasher स्विच के माध्यम से) के निष्पादन को सीमित कर रहा है। यह एक एनवायरनमेंट वेरिएबल ( BE_CRASHER=1 ) के जरिए एक फ्लैग में भी गुजरता है, जो दूसरे आवेश की जांच करता है और यदि सेट किया जाता है, सिस्टम-अंडर-टेस्ट को कॉल करता है, एक अनन्त लूप में चलने से रोकने के तुरंत बाद लौटता है। इस प्रकार, हमें वापस हमारे मूल कॉल साइट पर वापस छोड़ा जा रहा है और अब वास्तविक निकास कोड को मान्य कर सकते हैं।

स्रोत: एंड्रयू की प्रस्तुति के स्लाइड 23 दूसरी स्लाइड में प्रस्तुति के वीडियो के लिए लिंक भी शामिल है वह 47:09 पर उप- प्रोसेस परीक्षण के बारे में बात करता है

इस कोड को देखते हुए

func doomed() {
  os.Exit(1)
}

मैं कैसे ठीक से यह परीक्षण कर सकता हूँ कि इस फ़ंक्शन को कॉल करने से परिणाम का उपयोग करते हुए एक मौजूद go test ? यह परीक्षणों के एक सूट के भीतर होने की जरूरत है, दूसरे शब्दों में os.Exit() कॉल अन्य परीक्षणों को प्रभावित नहीं कर सकता है और इसे फंस जाना चाहिए।


मैं इसे बंद / बंदर का उपयोग करके करता हूं :

func TestDoomed(t *testing.T) {
  fakeExit := func(int) {
    panic("os.Exit called")      
  }
  patch := monkey.Patch(os.Exit, fakeExit)
  defer patch.Unpatch()
  assert.PanicsWithValue(t, "os.Exit called", doomed, "os.Exit was not called")
}

बंदर इस तरह के काम की बात आती है, और गलती इंजेक्शन और अन्य मुश्किल कार्यों के लिए बंदर सुपर शक्तिशाली है। यह कुछ चेतावनियों के साथ आता है।


मुझे नहीं लगता कि आप वास्तविक से परीक्षण कर सकते हैं। os.Exit बिना बाहर से परीक्षण ( exec.Command ) प्रक्रिया के बिना।

उस ने कहा, आप एक इंटरफ़ेस या फ़ंक्शन प्रकार बनाकर अपने लक्ष्य को पूरा कर सकते हैं और फिर अपने परीक्षणों में एक नॉप कार्यान्वयन का उपयोग कर सकते हैं:

खेल का मैदान जाओ

package main

import "os"
import "fmt"

type exiter func (code int)

func main() {
    doExit(func(code int){})
    fmt.Println("got here")
    doExit(func(code int){ os.Exit(code)})
}

func doExit(exit exiter) {
    exit(1)
}

आप नहीं कर सकते, आपको exec.Command का उपयोग करना होगा और लौटा मूल्य का परीक्षण करना होगा।







exit-code