Exemplo n.º 1
0
        /// <summary>
        /// Run the unit tests.
        /// </summary>
        public async void RunAsync()
        {
            // Ensure there's an interface to display the test results.
            if (this.Reporter == null)
            {
                throw new ArgumentNullException("Reporter");
            }

            // Setup the progress/failure counters
            this.Progress = 0;
            this.Failures = 0;

            // Filter out any test methods based on the current settings
            int filteredTestCount = FilterTests();

            // Write out the test status message which may be modified by the
            // filters
            Reporter.Status(this.Settings.TestRunStatusMessage);

            // Enumerators that track the current group and method to execute
            // (which allows reentrancy into the test loop below to resume at
            // the correct location).
            IEnumerator <TestGroup>  groups  = this.Groups.OrderBy(g => g.Name).GetEnumerator();
            IEnumerator <TestMethod> methods = null;

            // Keep a reference to the current group so we can pass it to the
            // Reporter's EndGroup (we don't need one for the test method,
            // however, because we close over in the continuation).
            TestGroup currentGroup = null;

            // Setup the UI
            this.Reporter.StartRun(this);

            // The primary test loop is a "recursive" closure that will pass
            // itself as the continuation to async tests.
            //
            // Note: It's really important for performance to note that any
            // calls to testLoop only occur in the tail position.
            DateTime    RunStartTime = DateTime.UtcNow;
            Func <Task> testLoop     = null;

            testLoop =
                async() =>
            {
                if (methods != null && methods.MoveNext())
                {
                    // If we were in the middle of a test group and there
                    // are more methods to execute, let's move to the next
                    // test method.

                    // Update the progress
                    this.Progress++;
                    Reporter.Progress(this);
                    // Start the test method
                    Reporter.StartTest(methods.Current);
                    if (methods.Current.Excluded)
                    {
                        // Ignore excluded tests and immediately recurse.
                        Reporter.EndTest(methods.Current);
                        await testLoop();
                    }
                    else
                    {
                        // Get the start time for individual tests
                        DateTime testStartTime = DateTime.UtcNow;

                        // Record the test result, upload the test log as a blob and clear the
                        // log for next test
                        Func <Task> recordTestResult = async() =>
                        {
                            if (!Settings.ManualMode)
                            {
                                // upload test log to sunlight blob container
                                string relativeFilePath = this.Platform + "/" + Guid.NewGuid().ToString() + ".txt";

                                string blobStorageSasUrl = GetBlobStorageSasUrl(this.Settings.Custom["TestFrameworkStorageContainerUrl"],
                                                                                this.Settings.Custom["TestFrameworkStorageContainerSasToken"],
                                                                                relativeFilePath);

                                await UploadToBlobContainerAsync(blobStorageSasUrl, LogDump.ToString());

                                // record the test result
                                var testResult = new TestResult()
                                {
                                    FullName     = methods.Current.Name,
                                    StartTime    = testStartTime,
                                    EndTime      = DateTime.UtcNow,
                                    Outcome      = methods.Current.Passed ? "Passed" : "Failed",
                                    Source       = currentGroup.Name,
                                    ReferenceUrl = relativeFilePath
                                };

                                // Add the test result to the test result collection
                                testRun.AddTestResult(testResult);
                                LogDump.Clear();
                            }
                        };
                        // Execute the test method
                        methods.Current.Test.Start(
                            new ActionContinuation
                        {
                            OnSuccess = async() =>
                            {
                                // Mark the test as passing, update the
                                // UI, and continue with the next test.
                                methods.Current.Passed = true;
                                methods.Current.Test   = null;
                                Reporter.EndTest(methods.Current);
                                await recordTestResult();
                                await testLoop();
                            },
                            OnError = async(message) =>
                            {
                                // Mark the test as failing, update the
                                // UI, and continue with the next test.
                                methods.Current.Passed    = false;
                                methods.Current.Test      = null;
                                methods.Current.ErrorInfo = message;
                                this.Failures++;
                                System.Diagnostics.Debug.WriteLine(message);
                                Reporter.Error(message);
                                LogDump.AppendLine(message);
                                Reporter.EndTest(methods.Current);
                                await recordTestResult();
                                await testLoop();
                            }
                        });
                    }
                }
                else if (groups.MoveNext())
                {
                    // If we've finished a test group and there are more,
                    // then move to the next one.

                    // Finish the UI for the last group.
                    if (currentGroup != null)
                    {
                        Reporter.EndGroup(currentGroup);
                        currentGroup = null;
                    }

                    // Setup the UI for this next group
                    currentGroup = groups.Current;
                    Reporter.StartGroup(currentGroup);

                    // Get the methods and immediately recurse which will
                    // start executing them.
                    methods = groups.Current.Methods.OrderBy(m => m.Name).GetEnumerator();
                    await testLoop();
                }
                else
                {
                    if (!Settings.ManualMode)
                    {
                        // upload test suite result to sunlight blob container
                        string blobStorageSasUrl = GetBlobStorageSasUrl(this.Settings.Custom["TestFrameworkStorageContainerUrl"],
                                                                        this.Settings.Custom["TestFrameworkStorageContainerSasToken"],
                                                                        this.Platform + "-detail.json");
                        string fileContent = JsonConvert.SerializeObject(testRun.TestResults.ToList(), Formatting.Indented);
                        await UploadToBlobContainerAsync(blobStorageSasUrl, fileContent);

                        // upload test result summary to blob container
                        var masterResult = new MasterTestResult()
                        {
                            FullName     = this.Platform + "-" + Settings.Custom["RuntimeVersion"],
                            Outcome      = Failures > 0 ? "Failed" : "Passed",
                            TotalCount   = testRun.TestCount,
                            Passed       = filteredTestCount - Failures,
                            Failed       = Failures,
                            Skipped      = testRun.TestCount - filteredTestCount,
                            StartTime    = RunStartTime,
                            EndTime      = DateTime.UtcNow,
                            ReferenceUrl = this.Platform + "-detail.json"
                        };

                        // upload test suite result to sunlight blob container
                        blobStorageSasUrl = GetBlobStorageSasUrl(this.Settings.Custom["TestFrameworkStorageContainerUrl"],
                                                                 this.Settings.Custom["TestFrameworkStorageContainerSasToken"],
                                                                 this.Platform + "-master.json");
                        fileContent = JsonConvert.SerializeObject(masterResult, Formatting.Indented);
                        await UploadToBlobContainerAsync(blobStorageSasUrl, fileContent);
                    }
                    // Otherwise if we've finished the entire test run

                    // Finish the UI for the last group and update the
                    // progress after the very last test method.
                    Reporter.EndGroup(currentGroup);
                    Reporter.Progress(this);

                    // Finish the UI for the test run.
                    Reporter.EndRun(this);
                }
            };

            // Start running the tests
            await testLoop();
        }
        /// <summary>
        /// Run the unit tests.
        /// </summary>
        public async void RunAsync()
        {
            // Ensure there's an interface to display the test results.
            if (this.Reporter == null)
            {
                throw new ArgumentNullException("Reporter");
            }

            // Setup the progress/failure counters
            this.Progress = 0;
            this.Failures = 0;

            // Filter out any test methods based on the current settings
            int filteredTestCount = FilterTests();

            // Write out the test status message which may be modified by the
            // filters
            Reporter.Status(this.Settings.TestRunStatusMessage);

            // Enumerators that track the current group and method to execute
            // (which allows reentrancy into the test loop below to resume at
            // the correct location).
            IEnumerator<TestGroup> groups = this.Groups.OrderBy(g => g.Name).GetEnumerator();
            IEnumerator<TestMethod> methods = null;

            // Keep a reference to the current group so we can pass it to the
            // Reporter's EndGroup (we don't need one for the test method,
            // however, because we close over in the continuation).
            TestGroup currentGroup = null;

            // Setup the UI
            this.Reporter.StartRun(this);

            // The primary test loop is a "recursive" closure that will pass
            // itself as the continuation to async tests.
            // 
            // Note: It's really important for performance to note that any
            // calls to testLoop only occur in the tail position.
            DateTime RunStartTime = DateTime.UtcNow;
            Func<Task> testLoop = null;

            testLoop =
                async () =>
                {
                    if (methods != null && methods.MoveNext())
                    {
                        // If we were in the middle of a test group and there
                        // are more methods to execute, let's move to the next
                        // test method.

                        // Update the progress
                        this.Progress++;
                        Reporter.Progress(this);
                        // Start the test method
                        Reporter.StartTest(methods.Current);
                        if (methods.Current.Excluded)
                        {
                            // Ignore excluded tests and immediately recurse.
                            Reporter.EndTest(methods.Current);
                            await testLoop();
                        }
                        else
                        {
                            // Get the start time for individual tests
                            DateTime testStartTime = DateTime.UtcNow;

                            // Record the test result, upload the test log as a blob and clear the 
                            // log for next test
                            Func<Task> recordTestResult = async () =>
                            {
                                if (!Settings.ManualMode)
                                {
                                     // upload test log to sunlight blob container
                                    string relativeFilePath = this.Platform + "/" + Guid.NewGuid().ToString() + ".txt";

                                    string blobStorageSasUrl = GetBlobStorageSasUrl(this.Settings.Custom["TestFrameworkStorageContainerUrl"],
                                        this.Settings.Custom["TestFrameworkStorageContainerSasToken"],
                                        relativeFilePath);

                                    await UploadToBlobContainerAsync(blobStorageSasUrl, LogDump.ToString());

                                    // record the test result
                                    var testResult = new TestResult()
                                    {
                                        FullName = methods.Current.Name,
                                        StartTime = testStartTime,
                                        EndTime = DateTime.UtcNow,
                                        Outcome = methods.Current.Passed ? "Passed" : "Failed",
                                        Source = currentGroup.Name,
                                        ReferenceUrl = relativeFilePath
                                    };

                                    // Add the test result to the test result collection
                                    testRun.AddTestResult(testResult);
                                    LogDump.Clear();
                                }
                            };
                            // Execute the test method
                            methods.Current.Test.Start(
                                new ActionContinuation
                                {
                                    OnSuccess = async () =>
                                    {
                                        // Mark the test as passing, update the
                                        // UI, and continue with the next test.
                                        methods.Current.Passed = true;
                                        methods.Current.Test = null;
                                        Reporter.EndTest(methods.Current);
                                        await recordTestResult();
                                        await testLoop();
                                    },
                                    OnError = async (message) =>
                                    {
                                        // Mark the test as failing, update the
                                        // UI, and continue with the next test.
                                        methods.Current.Passed = false;
                                        methods.Current.Test = null;
                                        methods.Current.ErrorInfo = message;
                                        this.Failures++;
                                        System.Diagnostics.Debug.WriteLine(message);
                                        Reporter.Error(message);
                                        LogDump.AppendLine(message);
                                        Reporter.EndTest(methods.Current);
                                        await recordTestResult();
                                        await testLoop();
                                    }
                                });
                        }

                    }
                    else if (groups.MoveNext())
                    {
                        // If we've finished a test group and there are more,
                        // then move to the next one.

                        // Finish the UI for the last group.
                        if (currentGroup != null)
                        {
                            Reporter.EndGroup(currentGroup);
                            currentGroup = null;
                        }

                        // Setup the UI for this next group
                        currentGroup = groups.Current;
                        Reporter.StartGroup(currentGroup);

                        // Get the methods and immediately recurse which will
                        // start executing them.
                        methods = groups.Current.Methods.OrderBy(m => m.Name).GetEnumerator();
                        await testLoop();
                    }
                    else
                    {
                        if (!Settings.ManualMode)
                        {
                            // upload test suite result to sunlight blob container
                            string detailFilePath = string.Format("{0}-{1}-detail.json", this.Settings.Custom["RuntimeVersion"], this.Platform);
                            string blobStorageSasUrl = GetBlobStorageSasUrl(this.Settings.Custom["TestFrameworkStorageContainerUrl"],
                                this.Settings.Custom["TestFrameworkStorageContainerSasToken"],
                                detailFilePath);
                            string fileContent = JsonConvert.SerializeObject(testRun.TestResults.ToList(), Formatting.Indented);
                            await UploadToBlobContainerAsync(blobStorageSasUrl, fileContent);

                            // upload test result summary to blob container
                            var masterResult = new MasterTestResult()
                            {
                                FullName = Settings.Custom["RuntimeVersion"] + "-" + this.Platform,
                                Backend = Settings.Custom["RuntimeVersion"],
                                Outcome = Failures > 0 ? "Failed" : "Passed",
                                TotalCount = testRun.TestCount,
                                Passed = filteredTestCount - Failures,
                                Failed = Failures,
                                Skipped = testRun.TestCount - filteredTestCount,
                                StartTime = RunStartTime,
                                EndTime = DateTime.UtcNow,
                                ReferenceUrl = Settings.Custom["RuntimeVersion"] + "-" + this.Platform + "-detail.json"
                            };

                            // upload test suite result to sunlight blob container
                            string masterFilePath = string.Format("{0}-{1}-master.json", this.Settings.Custom["RuntimeVersion"], this.Platform);
                            blobStorageSasUrl = GetBlobStorageSasUrl(this.Settings.Custom["TestFrameworkStorageContainerUrl"],
                                this.Settings.Custom["TestFrameworkStorageContainerSasToken"],
                                masterFilePath);
                            fileContent = JsonConvert.SerializeObject(masterResult, Formatting.Indented);
                            await UploadToBlobContainerAsync(blobStorageSasUrl, fileContent);
                        }
                        // Otherwise if we've finished the entire test run

                        // Finish the UI for the last group and update the
                        // progress after the very last test method.
                        Reporter.EndGroup(currentGroup);
                        Reporter.Progress(this);

                        // Finish the UI for the test run.
                        Reporter.EndRun(this);
                    }
                };

            // Start running the tests
            await testLoop();
        }