2013-08-12 7 views
13

मैं निम्नलिखित async कार्यप्रवाह (NUnit + FsUnit के साथ) परीक्षण करना चाहते हैं:जब एफ # async परीक्षण कैसे एक उपयोगी स्टैकट्रेस पाने के लिए कार्यप्रवाह

let foo = async { 
    failwith "oops" 
    return 42 
} 

मैं इसके लिए निम्न परीक्षण लिखा है:

let [<Test>] TestFoo() = 
    foo 
    |> Async.RunSynchronously 
    |> should equal 42 

के बाद से foo फेंकता मैं इकाई परीक्षण धावक में निम्नलिखित स्टैकट्रेस मिलती है:

System.Exception : oops 
    at Microsoft.FSharp.Control.CancellationTokenOps.RunSynchronously(CancellationToken token, FSharpAsync`1 computation, FSharpOption`1 timeout) 
    at Microsoft.FSharp.Control.FSharpAsync.RunSynchronously(FSharpAsync`1 computation, FSharpOption`1 timeout, FSharpOption`1 cancellationToken) 
    at ExplorationTests.TestFoo() in ExplorationTests.fs: line 76 

दुर्भाग्य स्टैकट्रेस हिरण मुझे बताओ कि अपवाद कहाँ उठाया गया था। यह RunSynchronously पर बंद हो जाता है।

कहीं मैंने सुना है कि Async.Catch जादुई स्टैकट्रेस पुनर्स्थापित करता है, इसलिए मैं अपने परीक्षण समायोजित:

let [<Test>] TestFooWithBetterStacktrace() = 
    foo 
    |> Async.Catch 
    |> Async.RunSynchronously 
    |> fun x -> match x with 
       | Choice1Of2 x -> x |> should equal 42 
       | Choice2Of2 ex -> raise (new System.Exception(null, ex)) 

अब इस बदसूरत है लेकिन कम से कम यह एक उपयोगी स्टैकट्रेस पैदा करता है:

System.Exception : Exception of type 'System.Exception' was thrown. 
    ----> System.Exception : oops 
    at Microsoft.FSharp.Core.Operators.Raise(Exception exn) 
    at ExplorationTests.TestFooWithBetterStacktrace() in ExplorationTests.fs: line 86 
--Exception 
    at Microsoft.FSharp.Core.Operators.FailWith(String message) 
    at [email protected](Unit unitVar) in ExplorationTests.fs: line 71 
    at [email protected](AsyncParams`1 args) 

यह समय स्टैकट्रैक दिखाता है कि त्रुटि वास्तव में कहां है: [email protected] 71

Async.Catch से छुटकारा पाने और दो विकल्पों के बीच मिलान करने का कोई तरीका है जबकि अभी भी उपयोगी stacktraces हो रही है? एसिंक वर्कफ़्लो परीक्षणों को ढांचा बनाने का कोई बेहतर तरीका है?

+1

मुझे एक ही समस्या और Async था।कैच एकमात्र कामकाज था जिसे मैं –

+0

पाया था, मैंने डॉन सिमे को ईमेल किया है, जिन्होंने सुझाव दिया कि यह एक मौलिक .NET सीमा थी, और 'Async.Catch' एकमात्र विकल्प था। –

+0

@JohnPalmer मुझे जवाब देने की तरह लगता है – mydogisbox

उत्तर

5

Async.Catch के बाद से और अपवाद rethrowing एक उपयोगी स्टैकट्रेस मैं के साथ निम्न आया पाने के लिए एक ही रास्ता होने लगते हैं) "। यह सबसे अच्छा तरीका है कि कोई अपने स्टैकट्रैस को दूषित किए बिना अपवाद को दोबारा हटा सकता है (नकारात्मक: केवल .NET 4.5 के बाद से उपलब्ध)।

अब मैं उस तरह परीक्षण "TestFooWithBetterStacktrace" पुनर्लेखन कर सकते हैं:

let [<Test>] TestFooWithBetterStacktrace() = 
    foo 
    |> Async.Catch 
    |> Async.RunSynchronously 
    |> Async.Rethrow 
    |> should equal 42 

परीक्षण ज्यादा बेहतर लग रहा है, rethrowing कोड चूसना नहीं करता है (के रूप में ज्यादा के रूप में पहले) और मैं परीक्षा में उपयोगी stacktraces मिल जब कुछ गलत हो जाता है तो धावक।

+0

+1 यह एक अच्छा कामकाज की तरह लगता है। – Daniel

3

कुछ ईमेल है कि मैं डॉन सायमे भेजे गए एक समय पहले से हवाला देते हुए:

अगर आप सेट करके देखें डिबग अनुभव में सुधार करना चाहिए "सबसे पहले मौका अपवाद पकड़ो" डीबग में -> अपवाद -> CLR अपवाद । "जस्ट माई कोड" से को चालू करने से भी मदद मिल सकती है।

और

ठीक है। Async {...} के साथ, गणनाओं को बाध्य नहीं किया जाता है, इसलिए कुछ स्थानों पर उन्हें दाएं धागे पर वापस लाने के लिए अपवादों को पुनर्स्थापित करने की आवश्यकता है।

Async.Catch का न्यायसंगत उपयोग, या अन्य अपवाद हैंडलिंग भी सहायता कर सकते हैं।

type Async with 
    static member Rethrow x = 
    match x with 
     | Choice1Of2 x -> x 
     | Choice2Of2 ex -> ExceptionDispatchInfo.Capture(ex).Throw() 
         failwith "nothing to return, but will never get here" 

नोट "ExceptionDispatchInfo.Capture (पूर्व) .Throw (:

+0

हाय जॉन, उद्धरण # 1 पहली मौका अपवाद पर तोड़ने में सक्षम बनाता है क्योंकि वास्तव में कभी भी डीबगर का उपयोग नहीं करता है। मुझे इकाई परीक्षण धावक के आउटपुट में उपयोगी स्टैकट्रैस चाहिए। उद्धरण # 2 का मतलब यह है कि मैं पहले से ही अपने दूसरे टेस्ट (टेस्टफू विथबेटरस्टैकट्रैस) में कर रहा हूं? – stmax

+0

@stmax - मुझे लगता है कि आपका दूसरा परीक्षण अच्छा है। –

संबंधित मुद्दे