Created
November 17, 2016 09:57
-
-
Save bartelink/a00f3ba36071a14201776e44e6f4b16f to your computer and use it in GitHub Desktop.
Stash of a spike to grab TickSpec Scenarios during the xUnit 2 discovery phase in order to surface the Scenarios as individual Tests in the VS Test Runner list. AFAICT this will never work as it will require all of TickSpec's object model and more (the compiled code) to be serializable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace TickSpec | |
open System | |
open System.Reflection | |
open System.Threading.Tasks | |
open Xunit | |
open Xunit.Abstractions | |
open Xunit.Sdk | |
module Impl = | |
let scenariosfromtestMethod (testMethod: Xunit.Abstractions.ITestMethod) : seq<Scenario> = | |
Console.WriteLine ("scenariosfromtestMethod" + testMethod.Method.Name) | |
testMethod.Method.ToRuntimeMethod().Invoke(null, null) :?> seq<Scenario> | |
// Stolen from https://github.com/erecruit/Fuchu.Xunit/blob/6ba0a30c9c4010ef60eec851c21523a56728f40d/Fuchu.Xunit/Fuchu.Xunit.fs | |
type private TestCase(bus, methd, display, label) = | |
// NOTE: we're passing the test label as "test method arguments". We have to do this, | |
// because otherwise all our tests cases will look identical to Xunit, because they | |
// come from the same test method. But if we pass the label as "arguments", Xunit will | |
// include it in the test case identity, thus making these tests distinct. | |
inherit XunitTheoryTestCase(bus, TestMethodDisplay.ClassAndMethod, methd) | |
/// Required for Xunit's runner to be able to traverse AppDomains etc. | |
new() = new TestCase(null, null, null, null) | |
interface ITestCase with | |
member __.DisplayName = display | |
override this.RunAsync(_, bus:IMessageBus, _,_, _) : Task<RunSummary> = | |
let post (m: #IMessageSinkMessage) = bus.QueueMessage m |> ignore | |
let test = XunitTest(this, this.DisplayName) | |
let runFeature = async { | |
let runScenario (scenario : Scenario) = | |
let reportSuccess () = | |
post <| TestPassed(test, 0m, "") | |
RunSummary(Total = 1) | |
let reportExn (ex : exn) = | |
let ex = if ex.InnerException = null then ex else ex.InnerException | |
post <| TestFailed(test, 0m, "", ex) | |
RunSummary(Total = 1, Failed = 1) | |
Console.WriteLine scenario.Name | |
scenario.Action.Invoke() | |
try | |
reportSuccess () | |
with ex -> reportExn ex | |
post (TestStarting test) | |
let summary = RunSummary() | |
scenariosfromtestMethod methd | |
|> Seq.find (fun x-> x.Name = label) | |
|> runScenario | |
|> summary.Aggregate | |
return summary } | |
Async.StartAsTask(runFeature)//, ?cancellationToken = cancel.Token) | |
let discover (testMethod: Xunit.Abstractions.ITestMethod) bus : IXunitTestCase seq = | |
let makeCase (scenario : Scenario) = | |
let label = scenario.Name | |
let display = sprintf "%s.%s %s" testMethod.TestClass.Class.Name testMethod.Method.Name label | |
new TestCase(bus, testMethod, display, label) | |
scenariosfromtestMethod testMethod | |
|> Seq.map makeCase | |
|> Seq.cast | |
/// Xunit Marker Atrribute; Used to tag entrypoints from which Scenarios are yielded which can then be Discovered (via FeatureDiscover) and run | |
[<AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)>] | |
[<XunitTestCaseDiscoverer("TickSpec.FeatureDiscoverer", "FSharpXunit2")>] | |
type FeatureAttribute() = | |
inherit FactAttribute() | |
/// Xunit Discoverer; Used by an Xunit runner to Discover tests based on the FeatureAttribute tagging each Feature entry-point | |
type FeatureDiscoverer(bus) = | |
interface IXunitTestCaseDiscoverer with | |
member __.Discover(_, testMethod, _) : IXunitTestCase seq = | |
Impl.discover testMethod bus |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment