/// <summary>
        /// The method that gets called when a test is executed
        /// </summary>
        /// <param name="args">arguments that are passed from the test signature</param>
        /// <returns></returns>
        public TestMethodInvokerResult Invoke(params object[] args)
        {
            // Our helper results class to aggregate our test results
            // Make sure we dispose it when done to get rid of our XmlTextWriter
            using (HelperTestGridResults results = new HelperTestGridResults(this.invokerContext.TestMethodInfo))
            {
                Assembly testMethodAssembly = this.invokerContext.TestMethodInfo.DeclaringType.Assembly;

                // Gets the custom attribute off the method
                RowAttribute[] rows = (RowAttribute[])this.invokerContext.TestMethodInfo.GetCustomAttributes(typeof(RowAttribute), false);

                IList<RowFilterAttribute> rowFilters = AttributeHelper.GetCustomAttributes<RowFilterAttribute>(this.invokerContext.TestMethodInfo, true);

                IList<TestExecutionAttribute> testExecutionAttributes = AttributeHelper.GetCustomAttributes<TestExecutionAttribute>(this.invokerContext.TestMethodInfo, true);
                TestExecutionAttribute testExecutionAggregateAttr = TestExecutionAttribute.Aggregate(testExecutionAttributes);

                Log.LogWriter logWriter = CreateLogWriter(testExecutionAggregateAttr);

                SetExpandedPaths(rows, this.invokerContext);
                IEnumerable<DataRowValues> dataRowValuesCollection = GetAllDataRowValues(rows, this.invokerContext, results);

                IEnumerable<RowTestContext> inputRowContexts = dataRowValuesCollection.Select(dataRowValues =>
                    {
                        object[] valuesArray = results.PrepareRowValues(dataRowValues);

                        RowTestContext rowTestContext = new RowTestContext(dataRowValues)
                        {
                            LogType = testExecutionAggregateAttr.LogType,
                            LogContentType = testExecutionAggregateAttr.LogContentType,
                            LogWriter = logWriter,
                            WriteHeaders = testExecutionAggregateAttr.WriteHeaders,
                            ValuesArray = valuesArray,
                            TestExecutionAttributes = testExecutionAttributes
                        };

                        PopulateRowSkippedInfo(invokerContext, rowTestContext, rowFilters);

                        return rowTestContext;
                    });

                IEnumerable<RowTestContext> outputRowContexts;

                if (testExecutionAggregateAttr.ExecuteInParallel)
                {
                    ParallelQuery<RowTestContext> query = inputRowContexts.AsParallel().AsOrdered();
                    if (testExecutionAggregateAttr.MaxDegreeOfParallelism > 0)
                    {
                        query = query.WithDegreeOfParallelism(testExecutionAggregateAttr.MaxDegreeOfParallelism);
                    }

                    outputRowContexts = query.Select(this.InvokeSingleRow);
                }
                else
                {
                    outputRowContexts = inputRowContexts.Select(this.InvokeSingleRow);
                }

                // enumerate row data and invoke the test case with each yield they give us
                foreach (RowTestContext rowTestContext in outputRowContexts)
                {
                    // Add results to our aggregator if it is either executed, or skipped but we are showing skipped rows in results
                    if (!rowTestContext.Ignored || rowTestContext.ShowSkipped)
                    {
                        results.AddTestResult(rowTestContext);
                    }
                }

                // Return the aggregated results for the row variatons in the TestMethod
                return results.GetAllResults();
            }
        }
        private static void PopulateRowSkippedInfo(TestMethodInvokerContext invokerContext, RowTestContext rowTestContext, IList<RowFilterAttribute> filters)
        {
            FilterInfo filterInfo = filters.Select(filter => filter.GetFilterInfo(invokerContext, rowTestContext.DataRowValues))
                .Aggregate(FilterInfo.None, (acc, f) => acc | f);

            rowTestContext.Ignored = false;
            rowTestContext.ShowSkipped = true;

            // Process execution flags.
            if ((filterInfo & FilterInfo.Exclude) != FilterInfo.None)
            {
                rowTestContext.Ignored = true;
            }

            if ((filterInfo & FilterInfo.Include) != FilterInfo.None)
            {
                rowTestContext.Ignored = false;
            }

            // Process display flags
            if ((filterInfo & FilterInfo.HideSkipped) != FilterInfo.None)
            {
                rowTestContext.ShowSkipped = false;
            }

            if ((filterInfo & FilterInfo.ShowSkipped) != FilterInfo.None)
            {
                rowTestContext.ShowSkipped = true;
            }

            if (rowTestContext.DataRowValues.Ignore)
            {
                rowTestContext.Ignored = true;
            }
        }
        private RowTestContext InvokeSingleRow(RowTestContext rowTestContext)
        {
            if (rowTestContext.Ignored)
            {
                return rowTestContext;
            }

            if (rowTestContext.LogType == Log.LogDetailsType.RowDetails)
            {
                rowTestContext.LogBuilder = new StringBuilder();
                rowTestContext.LogWriter = Log.LogWriter.CreateStringBuilderLogWriter(rowTestContext.LogBuilder, rowTestContext.LogType, rowTestContext.LogContentType);
            }

            if (rowTestContext.WriteHeaders)
            {
                if (rowTestContext.LogContentType == Log.LogDetailsContentType.Html)
                {
                    rowTestContext.LogWriter.WriteLine("<pre>");
                    rowTestContext.LogWriter.Write("<b>");
                }

                // Output header info as to which data input row we are now on,
                // so any WriteLines or exception messages are diusplayed in-context under it.
                // This is the best we can do to partition the output per data input row, since MSTest does not know
                // that one of its Testmethods is really logically broken down into N rows.

                rowTestContext.LogWriter.Write("[Test {0}] {1}", rowTestContext.DataRowValues.Id, rowTestContext.DataRowValues.Desc);

                if (rowTestContext.LogContentType == Log.LogDetailsContentType.Html)
                {
                    rowTestContext.LogWriter.Write("</b>");
                }

                rowTestContext.LogWriter.WriteLine(string.Empty);
            }

            // Execute the parameterize test method for the current data input row values we parsed.
            // The invocation context will have a non-null Exception property if something threw within it
            // (since MSTest catches it first to record it for their purposes).
            // So no try/catch wrapper or rethrowing is necessary on our part.
            RowTestContext.Current = rowTestContext;

            // Give every TestExecutionAttribute an option to override default Test Method Invoker.
            ITestMethodInvoker testMethodInvoker = rowTestContext.TestExecutionAttributes.Aggregate(
                this.invokerContext.InnerInvoker,
                (ITestMethodInvoker invoker, TestExecutionAttribute attr) =>
                    attr.OverrideTestMethodInvoker(invoker, this.invokerContext, rowTestContext));

            rowTestContext.InvokerResult = testMethodInvoker.Invoke(rowTestContext.ValuesArray);

            RowTestContext.Current = null;

            rowTestContext.ResultException = rowTestContext.InvokerResult.Exception;

            // Use the inner exception as the meaningful one for us, unless there isn't one.
            // Normally the "target of invocation" outer exception is just noise for our purposes,
            // unless there is nothing else to show.
            if (rowTestContext.ResultException != null &&
                rowTestContext.ResultException.GetType() == typeof(TargetInvocationException) &&
                rowTestContext.ResultException.InnerException != null)
            {
                rowTestContext.ResultException = rowTestContext.ResultException.InnerException;
            }

            // Check for expected exception.
            if (rowTestContext.DataRowValues.ExpectedException != null)
            {
                if (rowTestContext.ResultException != null)
                {
                    if (rowTestContext.DataRowValues.ExpectedException.IsAssignableFrom(rowTestContext.ResultException.GetType()))
                    {
                        rowTestContext.ResultException = null;
                    }
                    else
                    {
                        rowTestContext.ResultException = new AssertFailedException("Expected '" + rowTestContext.DataRowValues.ExpectedException.FullName + "' exception, but different exception has been thrown. See inner exception.", rowTestContext.ResultException);
                    }
                }
                else
                {
                    rowTestContext.ResultException = new AssertFailedException("Expected '" + rowTestContext.DataRowValues.ExpectedException.FullName + "' exception, but no exception has been thrown.");
                }
            }

            // Log exception
            if (rowTestContext.ResultException != null)
            {
                rowTestContext.ResultMessage = rowTestContext.ResultException.Message;

                if (rowTestContext.WriteHeaders)
                {
                    StringBuilder sb = new StringBuilder();
                    WriteException(sb, rowTestContext.LogContentType, rowTestContext.ResultException);
                    rowTestContext.LogWriter.WriteLine(sb.ToString());
                }
            }

            if (rowTestContext.WriteHeaders)
            {
                // Output data input row end
                rowTestContext.LogWriter.WriteStringLine("--------------------------");
                rowTestContext.LogWriter.WriteStringLine(string.Empty);

                if (rowTestContext.LogContentType == Log.LogDetailsContentType.Html)
                {
                    rowTestContext.LogWriter.WriteStringLine("</pre>");
                }
            }

            ((Log.LogWriter)rowTestContext.LogWriter).Flush();

            if (rowTestContext.LogType == Log.LogDetailsType.RowDetails)
            {
                rowTestContext.CustomValues.Add("Details", rowTestContext.LogBuilder.ToString());
                rowTestContext.CustomValues.Add("DetailsContentType", rowTestContext.LogContentType.ToString());
            }

            return rowTestContext;
        }
Пример #4
0
 public override ITestMethodInvoker OverrideTestMethodInvoker(ITestMethodInvoker testMethodInvoker, TestMethodInvokerContext originalInvokerContext, RowTestContext rowTestContext)
 {
     return new Invoker() { OriginalInvoker = testMethodInvoker };
 }