Task ITestDiscoverer.AnalyzeDocumentAsync(DocumentTestDiscoveryContext context)
        {
            if (context.CancellationToken.IsCancellationRequested)
            {
                return(Task.FromCanceled(context.CancellationToken));
            }

            using (var discoverySink = new TestDiscoveryVisitor())
                using (var xunit2 = new Xunit2Discoverer(
                           AppDomainSupport.Denied,
                           sourceInformationProvider: DummySourceInformationProvider.Instance,
                           assemblyInfo: new SourceAssemblyInfo(context),
                           xunitExecutionAssemblyPath: XunitExecutionAssemblyPath.Value,
                           verifyAssembliesOnDisk: false))
                {
                    xunit2.Find(includeSourceInformation: false, messageSink: discoverySink, discoveryOptions: TestFrameworkOptions.ForDiscovery());

                    while (!discoverySink.Finished.WaitOne(50))
                    {
                        if (context.CancellationToken.IsCancellationRequested)
                        {
                            break;
                        }

                        TrySendDiscoveredTestCases(context, discoverySink);
                    }

                    TrySendDiscoveredTestCases(context, discoverySink);
                }

            return(context.CancellationToken.IsCancellationRequested ?
                   Task.FromCanceled(context.CancellationToken) :
                   Task.CompletedTask);
        }
 public static IEnumerable <ITestCase> Find(this Xunit2Discoverer discoverer, Type type)
 {
     using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>())
     {
         discoverer.Find(type.FullName, false, sink, TestFrameworkOptions.ForDiscovery());
         sink.Finished.WaitOne();
         return(sink.Messages.OfType <ITestCaseDiscoveryMessage>().Select(message => message.TestCase).ToList());
     }
 }
Ejemplo n.º 3
0
        public static IEnumerable <ITestCase> Find(this Xunit2Discoverer discoverer, Type type)
        {
#pragma warning disable IDE0063 // 'using' statement can be simplified
            using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>())
            {
                discoverer.Find(type.FullName, false, sink, TestFrameworkOptions.ForDiscovery());
                sink.Finished.WaitOne();
                return(sink.Messages.OfType <ITestCaseDiscoveryMessage>()
                       .Select(message => message.TestCase).ToArray());
            }
#pragma warning restore IDE0063 // 'using' statement can be simplified
        }
 public static IEnumerable <ITestCase> Find(this Xunit2Discoverer discoverer, string collectionName)
 {
     using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>())
     {
         discoverer.Find(false, sink, TestFrameworkOptions.ForDiscovery());
         sink.Finished.WaitOne();
         return(sink.Messages.OfType <ITestCaseDiscoveryMessage>()
                .Select(message => message.TestCase)
                .Where(message => message.TestMethod.TestClass.TestCollection.DisplayName == collectionName)
                .ToList());
     }
 }
Ejemplo n.º 5
0
        public static Queue <ITestCase> Find(this Xunit2Discoverer discoverer, Type type, TestAssemblyConfiguration testAssemblyConfiguration)
        {
            using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>())
            {
                discoverer.Find(type.FullName, false, sink, TestFrameworkOptions.ForDiscovery(testAssemblyConfiguration));
                sink.Finished.Wait();

                return(new Queue <ITestCase>(
                           sink.Messages.OfType <ITestCaseDiscoveryMessage>()
                           .Select(message => message.TestCase)));
            }
        }
Ejemplo n.º 6
0
        public static Queue <ITestCase> Find(this Xunit2Discoverer discoverer, string collectionName, TestAssemblyConfiguration testAssemblyConfiguration)
        {
            using (var sink = new SpyMessageSink <IDiscoveryCompleteMessage>())
            {
                discoverer.Find(false, sink, TestFrameworkOptions.ForDiscovery(testAssemblyConfiguration));
                sink.Finished.Wait();

                return(new Queue <ITestCase>(
                           sink.Messages.OfType <ITestCaseDiscoveryMessage>()
                           .Select(message => message.TestCase)
                           .Where(testCase => testCase.TestMethod.TestClass.TestCollection.DisplayName == collectionName)));
            }
        }
Ejemplo n.º 7
0
    static int Main(string[] args)
    {
        if (args.Length < 3)
        {
            Console.WriteLine("Usage: <outfile> <corefx dir> <test assembly filename> <xunit console options>");
            return(1);
        }

        var outfile_name = args [0];
        var sdkdir       = args [1] + "/artifacts/bin/runtime/netcoreapp-OSX-Debug-x64";

        args = args.Skip(2).ToArray();

        // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir
        File.Copy($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true);
        File.Copy($"{sdkdir}/CoreFx.Private.TestUtilities.dll", AppContext.BaseDirectory, true);
        File.Copy($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true);

        var cmdline = CommandLine.Parse(args);

        // Ditto
        File.Copy(cmdline.Project.Assemblies.First().AssemblyFilename, AppContext.BaseDirectory, true);

        var assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, Path.GetFileName(cmdline.Project.Assemblies.First().AssemblyFilename)));

        var msg_sink = new MsgSink();
        var xunit2   = new Xunit2Discoverer(AppDomainSupport.Denied, new NullSourceInformationProvider(), new ReflectionAssemblyInfo(assembly), null, null, msg_sink);
        var sink     = new TestDiscoverySink();
        var config   = new TestAssemblyConfiguration()
        {
            DiagnosticMessages = true, InternalDiagnosticMessages = true, PreEnumerateTheories = false
        };

        xunit2.Find(false, sink, TestFrameworkOptions.ForDiscovery(config));
        sink.Finished.WaitOne();

        foreach (XunitTestCase tc in sink.TestCases)
        {
            ComputeTraits(assembly, tc);
        }

        var w = File.CreateText(outfile_name);

        w.WriteLine("using System;");
        w.WriteLine("using System.Reflection;");
        w.WriteLine("public class RunTests {");
        w.WriteLine("\tpublic static int Main () {");
        w.WriteLine("\t\tint nrun = 0;");
        w.WriteLine("\t\tint nfailed = 0;");

        var filters = cmdline.Project.Filters;

        foreach (XunitTestCase tc in sink.TestCases)
        {
            var m = ((ReflectionMethodInfo)tc.Method).MethodInfo;
            //Console.WriteLine ("" + m.ReflectedType + " " + m + " " + (tc.TestMethodArguments == null));
            if (tc.TestMethodArguments != null || m.GetParameters().Length > 0)
            {
                continue;
            }
            var t = m.ReflectedType;
            if (t.IsGenericType)
            {
                continue;
            }

            /*
             * foreach (var trait in tc.Traits) {
             *      foreach (var s in trait.Value)
             *              Console.WriteLine (m.Name + " " + trait.Key + " " + s);
             * }
             */

            if (!filters.Filter(tc))
            {
                //Console.WriteLine ("FILTERED: " + m);
                continue;
            }

            string typename = GetTypeName(t);
            w.WriteLine($"Console.WriteLine (\"{typename}:{m.Name}...\");");
            w.WriteLine("\t\tnrun ++;");
            w.WriteLine("\t\ttry {");
            if (m.IsStatic)
            {
                if (!m.IsPublic)
                {
                    w.WriteLine($"\t\ttypeof({typename}).GetMethod (\"{m.Name}\", BindingFlags.Static|BindingFlags.NonPublic).Invoke(null, null);");
                }
                else
                {
                    w.WriteLine($"\t\t{typename}.{m.Name} ();");
                }
            }
            else
            {
                if (typeof(IDisposable).IsAssignableFrom(t))
                {
                    w.WriteLine($"\t\tusing (var o = new {typename} ()) {{");
                }
                else
                {
                    w.WriteLine("\t\t{");
                    w.WriteLine($"\t\t\tvar o = new {typename} ();");
                }
                w.WriteLine($"\t\t\to.{m.Name} ();");
                w.WriteLine("\t\t}");
            }
            w.WriteLine("\t\t} catch (Exception ex) { nfailed ++; Console.WriteLine (\"FAILED: \" + ex); }");
            if (cmdline.StopOnFail)
            {
                w.WriteLine("\t\tif (nfailed > 0) return 1;");
            }
        }
        w.WriteLine("\t\tConsole.WriteLine (\"RUN: \" + nrun + \", FAILED: \" + nfailed);");
        w.WriteLine("\t\treturn 0;");
        w.WriteLine("\t}");
        w.WriteLine("}");
        w.Close();

        return(0);
    }
Ejemplo n.º 8
0
    static int Main(string[] args)
    {
        if (args.Length < 3)
        {
            Console.WriteLine("Usage: <out-dir> <corefx dir> <test assembly filename> <xunit console options>");
            return(1);
        }

        var testAssemblyName = Path.GetFileNameWithoutExtension(args [2]);
        var testAssemblyFull = Path.GetFullPath(args[2]);
        var outdir_name      = Path.Combine(args [0], testAssemblyName);
        var sdkdir           = args [1] + "/artifacts/bin/runtime/netcoreapp-OSX-Debug-x64";

        args = args.Skip(2).ToArray();
        // Response file support
        var extra_args = new List <string> ();

        for (int i = 0; i < args.Length; ++i)
        {
            var arg = args [i];
            if (arg [0] == '@')
            {
                foreach (var line in File.ReadAllLines(arg.Substring(1)))
                {
                    if (line.Length == 0 || line [0] == '#')
                    {
                        continue;
                    }
                    extra_args.AddRange(line.Split(' '));
                }
                args [i] = "";
            }
        }
        args = args.Where(s => s != String.Empty).Concat(extra_args).ToArray();

        // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir
//		File.Copy ($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true);
        File.Copy($"{sdkdir}/CoreFx.Private.TestUtilities.dll", AppContext.BaseDirectory, true);
        File.Copy($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true);

        var cmdline = CommandLine.Parse(args);

        // Ditto
        File.Copy(cmdline.Project.Assemblies.First().AssemblyFilename, AppContext.BaseDirectory, true);

        var assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, Path.GetFileName(cmdline.Project.Assemblies.First().AssemblyFilename)));

        var msg_sink = new MsgSink();
        var xunit2   = new Xunit2Discoverer(AppDomainSupport.Denied, new NullSourceInformationProvider(), new ReflectionAssemblyInfo(assembly), null, null, msg_sink);
        var sink     = new TestDiscoverySink();
        var config   = new TestAssemblyConfiguration()
        {
            DiagnosticMessages = true, InternalDiagnosticMessages = true, PreEnumerateTheories = false
        };

        xunit2.Find(false, sink, TestFrameworkOptions.ForDiscovery(config));
        sink.Finished.WaitOne();

        foreach (XunitTestCase tc in sink.TestCases)
        {
            ComputeTraits(assembly, tc);
        }

        // Compute testcase data
        var tc_data = new Dictionary <XunitTestCase, List <CaseData> > ();

        foreach (XunitTestCase tc in sink.TestCases)
        {
            var m = ((ReflectionMethodInfo)tc.Method).MethodInfo;
            var t = m.ReflectedType;

            var cases = new List <CaseData> ();

            if (m.GetParameters().Length > 0)
            {
                foreach (var cattr in m.GetCustomAttributes(true))
                {
                    if (cattr is InlineDataAttribute)
                    {
                        var data = ((InlineDataAttribute)cattr).GetData(null).First();
                        if (data == null)
                        {
                            data = new object [m.GetParameters().Length];
                        }
                        if (data.Length != m.GetParameters().Length)
                        {
                            throw new Exception();
                        }

                        bool unhandled = false;
                        foreach (var val in data)
                        {
                            if (val is float || val is double)
                            {
                                unhandled = true;
                            }
                            if (val is Type)
                            {
                                var type = val as Type;
                                if (!type.IsVisible)
                                {
                                    unhandled = true;
                                }
                            }
                            if (val is Enum)
                            {
                                if (!val.GetType().IsPublic)
                                {
                                    unhandled = true;
                                }
                            }
                        }
                        if (!unhandled)
                        {
                            cases.Add(new CaseData()
                            {
                                Values = data
                            });
                        }
                    }
                }
            }
            else
            {
                cases.Add(new CaseData());
            }
            tc_data [tc] = cases;
        }

#if FALSE
        //w.WriteLine ($"\t\ttypeof({typename}).GetMethod (\"{m.Name}\", BindingFlags.Static|BindingFlags.NonPublic).Invoke(null, null);");
        //w.WriteLine ($"\t\tusing (var o = new {typename} ()) {{");
        //if (cmdline.StopOnFail)
        //w.WriteLine ("\t\tif (nfailed > 0) return 1;");
        //w.WriteLine ("\t\tConsole.WriteLine (\"RUN: \" + nrun + \", FAILED: \" + nfailed);");
#endif

        var cu = new CodeCompileUnit();
        var ns = new CodeNamespace("");
        cu.Namespaces.Add(ns);
        ns.Imports.Add(new CodeNamespaceImport("System"));
        ns.Imports.Add(new CodeNamespaceImport("System.Reflection"));
        var code_class = new CodeTypeDeclaration("RunTests");
        ns.Types.Add(code_class);

        var code_main = new CodeEntryPointMethod();
        code_main.ReturnType = new CodeTypeReference("System.Int32");
        code_class.Members.Add(code_main);

        var statements = code_main.Statements;
        statements.Add(new CodeVariableDeclarationStatement(typeof(int), "nrun", new CodePrimitiveExpression(0)));
        statements.Add(new CodeVariableDeclarationStatement(typeof(int), "nfailed", new CodePrimitiveExpression(0)));

        int nskipped = 0;

        var filters = cmdline.Project.Filters;
        foreach (XunitTestCase tc in sink.TestCases)
        {
            var m = ((ReflectionMethodInfo)tc.Method).MethodInfo;
            //Console.WriteLine ("" + m.ReflectedType + " " + m + " " + (tc.TestMethodArguments == null));
            var t = m.ReflectedType;
            if (t.IsGenericType)
            {
                nskipped++;
                continue;
            }
            if (!filters.Filter(tc))
            {
                nskipped++;
                continue;
            }

            var cases = tc_data [tc];

            int caseindex = 0;
            foreach (var test in cases)
            {
                string typename = GetTypeName(t);
                string msg;
                if (cases.Count > 1)
                {
                    msg = $"{typename}.{m.Name}[{caseindex}] ...";
                }
                else
                {
                    msg = $"{typename}.{m.Name} ...";
                }
                caseindex++;
                statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] { new CodePrimitiveExpression(msg) }));
                statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("nrun"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("nrun"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))));
                var try1 = new CodeTryCatchFinallyStatement();
                statements.Add(try1);
                if (!m.IsStatic)
                {
                    // FIXME: Disposable
                    try1.TryStatements.Add(new CodeVariableDeclarationStatement("var", "o", new CodeObjectCreateExpression(t, new CodeExpression[] {})));
                }
                if (!m.IsPublic)
                {
                    // FIXME:
                    nskipped++;
                }
                else
                {
                    CodeMethodInvokeExpression call;

                    if (m.IsStatic)
                    {
                        call = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(t), m.Name, new CodeExpression [] {});
                    }
                    else
                    {
                        call = new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("o"), m.Name, new CodeExpression [] {});
                    }

                    if (test.Values != null)
                    {
                        var parameters = m.GetParameters();
                        for (var index = 0; index < test.Values.Length; index++)
                        {
                            var val = test.Values [index];
                            call.Parameters.Add(EncodeValue(val, parameters [index].ParameterType));
                        }
                    }
                    try1.TryStatements.Add(call);
                }
                var catch1 = new CodeCatchClause("ex", new CodeTypeReference("System.Exception"));
                catch1.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("nfailed"), new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("nfailed"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))));
                catch1.Statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] {
                    new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression("FAILED: "),
                        CodeBinaryOperatorType.Add,
                        new CodeVariableReferenceExpression("ex"))
                }));
                try1.CatchClauses.Add(catch1);
            }
        }

        statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] {
            new CodeBinaryOperatorExpression(
                new CodePrimitiveExpression("RUN: "),
                CodeBinaryOperatorType.Add,
                new CodeVariableReferenceExpression("nrun"))
        }));
        statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] {
            new CodeBinaryOperatorExpression(
                new CodePrimitiveExpression("FAILURES: "),
                CodeBinaryOperatorType.Add,
                new CodeVariableReferenceExpression("nfailed"))
        }));
        statements.Add(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("Console"), "WriteLine", new CodeExpression [] {
            new CodeBinaryOperatorExpression(
                new CodePrimitiveExpression("SKIPPED: "),
                CodeBinaryOperatorType.Add,
                new CodePrimitiveExpression(nskipped))
        }));
        statements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(0)));


        Directory.CreateDirectory(outdir_name);
        var outfile_name = Path.Combine(outdir_name, "runner.cs");
        var provider     = new CSharpCodeProvider();
        using (var w2 = File.CreateText(outfile_name)) {
            provider.GenerateCodeFromCompileUnit(cu, w2, new CodeGeneratorOptions());
        }

        var csproj_template = File.ReadAllText("gen-test.csproj.template");
        csproj_template = csproj_template.Replace("#XUNIT_LOCATION#", sdkdir);
        csproj_template = csproj_template.Replace("#TEST_ASSEMBLY#", testAssemblyName);
        csproj_template = csproj_template.Replace("#TEST_ASSEMBLY_LOCATION#", testAssemblyFull);

        File.WriteAllText(Path.Combine(outdir_name, testAssemblyName + "-runner.csproj"), csproj_template);

        return(0);
    }
Ejemplo n.º 9
0
    static int Main(string[] args)
    {
        if (args.Length < 3)
        {
            Console.WriteLine("Usage: <out-dir> <corefx dir> <test assembly filename> <xunit console options>");
            return(1);
        }

        var testAssemblyName = Path.GetFileNameWithoutExtension(args [2]);
        var testAssemblyFull = Path.GetFullPath(args[2]);
        var outdir_name      = Path.Combine(args [0], testAssemblyName);
        var sdkdir           = args [1] + "/artifacts/bin/runtime/netcoreapp-OSX-Debug-x64";

        args = args.Skip(2).ToArray();
        // Response file support
        var extra_args = new List <string> ();

        for (int i = 0; i < args.Length; ++i)
        {
            var arg = args [i];
            if (arg [0] == '@')
            {
                foreach (var line in File.ReadAllLines(arg.Substring(1)))
                {
                    if (line.Length == 0 || line [0] == '#')
                    {
                        continue;
                    }
                    extra_args.AddRange(line.Split(' '));
                }
                args [i] = "";
            }
        }
        args = args.Where(s => s != String.Empty).Concat(extra_args).ToArray();

        // Despite a lot of effort, couldn't get dotnet to load these assemblies from the sdk dir, so copy them to our binary dir
//		File.Copy ($"{sdkdir}/Microsoft.DotNet.PlatformAbstractions.dll", AppContext.BaseDirectory, true);
        File.Copy($"{sdkdir}/CoreFx.Private.TestUtilities.dll", AppContext.BaseDirectory, true);
        File.Copy($"{sdkdir}/Microsoft.DotNet.XUnitExtensions.dll", AppContext.BaseDirectory, true);

        var cmdline = CommandLine.Parse(args);

        // Ditto
        File.Copy(cmdline.Project.Assemblies.First().AssemblyFilename, AppContext.BaseDirectory, true);

        var assembly = Assembly.LoadFrom(Path.Combine(AppContext.BaseDirectory, Path.GetFileName(cmdline.Project.Assemblies.First().AssemblyFilename)));

        var msg_sink = new MsgSink();
        var xunit2   = new Xunit2Discoverer(AppDomainSupport.Denied, new NullSourceInformationProvider(), new ReflectionAssemblyInfo(assembly), null, null, msg_sink);
        var sink     = new TestDiscoverySink();
        var config   = new TestAssemblyConfiguration()
        {
            DiagnosticMessages = true, InternalDiagnosticMessages = true, PreEnumerateTheories = false
        };

        xunit2.Find(false, sink, TestFrameworkOptions.ForDiscovery(config));
        sink.Finished.WaitOne();

        foreach (XunitTestCase tc in sink.TestCases)
        {
            ComputeTraits(assembly, tc);
        }

        // Compute testcase data
        var tc_data = new Dictionary <XunitTestCase, List <TcCase> > ();

        foreach (XunitTestCase tc in sink.TestCases)
        {
            var m = ((ReflectionMethodInfo)tc.Method).MethodInfo;
            var t = m.ReflectedType;

            var cases = new List <TcCase> ();

            if (m.GetParameters().Length > 0)
            {
                foreach (var cattr in m.GetCustomAttributes(true))
                {
                    if (cattr is InlineDataAttribute)
                    {
                        var data = ((InlineDataAttribute)cattr).GetData(null).First();
                        if (data == null)
                        {
                            data = new object [m.GetParameters().Length];
                        }
                        if (data.Length != m.GetParameters().Length)
                        {
                            throw new Exception();
                        }

                        bool unhandled = false;
                        foreach (var val in data)
                        {
                            if (val is float || val is double)
                            {
                                unhandled = true;
                            }
                            if (val is Type)
                            {
                                var type = val as Type;
                                if (!type.IsVisible)
                                {
                                    unhandled = true;
                                }
                            }
                            if (val is Enum)
                            {
                                if (!val.GetType().IsPublic)
                                {
                                    unhandled = true;
                                }
                            }
                        }
                        if (!unhandled)
                        {
                            cases.Add(new TcCase()
                            {
                                Values = data
                            });
                        }
                    }
                    else if (cattr is MemberDataAttribute memberData && memberData.Parameters.Length == 0)
                    {
                        MethodInfo testDataMethod = m.DeclaringType.GetMethod(memberData.MemberName);
                        if (testDataMethod == null)
                        {
                            continue;
                        }
                        cases.Add(new TcCase {
                            MemberDataMethod = testDataMethod
                        });
                    }
                }
            }
            else
            {
                cases.Add(new TcCase());
            }
            tc_data [tc] = cases;
        }

        var filters = cmdline.Project.Filters;

        //
        // Generate code using the roslyn syntax apis
        // Creating syntax nodes one-by-one is very cumbersome, so use
        // CSharpSyntaxTree.ParseText () to create them and ReplaceNode () to insert them into syntax trees.
        //
        var blocks = new List <BlockSyntax> ();

        foreach (XunitTestCase tc in sink.TestCases)
        {
            var m = ((ReflectionMethodInfo)tc.Method).MethodInfo;
            //Console.WriteLine ("" + m.ReflectedType + " " + m + " " + (tc.TestMethodArguments == null));
            var t = m.ReflectedType;
            if (t.IsGenericType)
            {
                nskipped++;
                continue;
            }
            if (!filters.Filter(tc))
            {
                nskipped++;
                continue;
            }

            var cases = tc_data [tc];

            int caseindex = 0;
            foreach (var test in cases)
            {
                string typename = GetTypeName(t);
                string msg;

                if (cases.Count > 1)
                {
                    msg = $"{typename}.{m.Name}[{caseindex}] ...";
                }
                else
                {
                    msg = $"{typename}.{m.Name} ...";
                }
                caseindex++;

                var block = ParseText <BlockSyntax> (case_template
                                                     .Replace("#MSG#", msg)
                                                     .Replace("#NRUN#", test.MemberDataMethod == null ? "1" : ((IEnumerable)test.MemberDataMethod.Invoke(null, null)).Cast <object> ().Count().ToString()));
                // Obtain the node for the CALL () line
                var try_body_node = block.DescendantNodes().OfType <ExpressionStatementSyntax> ().Skip(2).First().Parent;
                // Replace with the generated call code
                var stmts = GenerateTcCall(t, test, m);
                blocks.Add(block.ReplaceNode(try_body_node, Block(stmts.ToArray())));
            }
        }

        var cu = CSharpSyntaxTree.ParseText(runner_template.Replace("#NSKIPPED#", nskipped.ToString())).GetRoot();

        // Replace the body of the Run () method with the generated body
        var run_body = cu.DescendantNodes().OfType <MethodDeclarationSyntax> ().First().DescendantNodes().OfType <BlockSyntax> ().First();

        cu = cu.ReplaceNode(run_body, Block(blocks.ToArray()));

        // Create runner.cs
        Directory.CreateDirectory(outdir_name);
        var outfile_name = Path.Combine(outdir_name, "runner.cs");

        File.WriteAllText(outfile_name, cu.NormalizeWhitespace().ToString());

        // Generate csproj file
        var csproj_template = File.ReadAllText("gen-test.csproj.template");

        csproj_template = csproj_template.Replace("#XUNIT_LOCATION#", sdkdir);
        csproj_template = csproj_template.Replace("#TEST_ASSEMBLY#", testAssemblyName);
        csproj_template = csproj_template.Replace("#TEST_ASSEMBLY_LOCATION#", testAssemblyFull);

        File.WriteAllText(Path.Combine(outdir_name, testAssemblyName + "-runner.csproj"), csproj_template);

        return(0);
    }