private static DataRowValues ReadRow(HelperTestGridResults results, XPathNavigator rowNode) { List<object> rowValuesList = new List<object>(); DataRowValues dataRowValues = new DataRowValues(); rowValuesList.Clear(); for (var elementNodes = rowNode.Select("*"); elementNodes.MoveNext(); ) { var elementNode = elementNodes.Current; switch (elementNode.Name) { case "Desc": dataRowValues.Desc = elementNode.Value; break; case "Ignore": dataRowValues.Ignore = elementNode.ValueAsBoolean; break; // Parse Bug also for back compat before we renamed it to Defect case "Bug": case "Defect": dataRowValues.Defect = elementNode.ValueAsInt; break; case "Id": dataRowValues.Id = elementNode.Value; break; case "Properties": dataRowValues.Properties = new Dictionary<string, object>(); for (var propertyNodes = elementNode.Select("*"); propertyNodes.MoveNext(); ) { var propertyNode = propertyNodes.Current; dataRowValues.Properties[propertyNode.Name] = propertyNode.Value; } break; default: // Each value is typed according to the test method formal args // If params are present in the signature, then the type of every optional value is the params element type Type dataType; if (rowValuesList.Count < results.NonParamsArgCount) { dataType = results.FormalArgs[rowValuesList.Count].ParameterType; } else { dataType = results.ParamArgElementType; } object value = elementNode.ValueAs(dataType, null); rowValuesList.Add(value); break; } } dataRowValues.Values = rowValuesList.ToArray(); return dataRowValues; }
/// <summary> /// Any XML stream source should use this method to yield row data. /// Both embedded and external XML files use this. /// </summary> /// <param name="results"></param> /// <param name="stream"></param> /// <param name="source"></param> /// <param name="section"></param> /// <param name="row"></param> /// <returns></returns> public static IEnumerable<DataRowValues> GetRows(HelperTestGridResults results, Stream stream, string source, string section, string row) { XPathDocument document = new XPathDocument(stream); XPathNavigator navigator = document.CreateNavigator(); var sectionNode = navigator.SelectSingleNode("//" + section); if (sectionNode != null) { for (var rowNodes = sectionNode.Select(row); rowNodes.MoveNext(); ) { var rowNode = rowNodes.Current; DataRowValues dataRowValues = ReadRow(results, rowNodes.Current); yield return dataRowValues; } } else { throw new InvalidOperationException(string.Format("The section element '{0}' was not found in the XML stream from '{1}'.", section, source)); } }
/// <summary> /// Enumerate row data. /// Each row this attribute represents is yielded. /// </summary> /// <param name="resourceAssembly">The assembly containing the resource stream. Unused for external file access.</param> /// <param name="results">The helper to access param and formal arg type info.</param> /// <returns>An enumeration of DataRowValues to drive test method.</returns> public override IEnumerable<DataRowValues> GetRowEnumerator(Assembly resourceAssembly, HelperTestGridResults results) { Stream stream = File.OpenRead(this.xmlExpandedPath); if (stream == null) { throw new FileNotFoundException(string.Format("The path '{0}' expanded from '{1}' could not be found.", this.xmlExpandedPath, this.xmlPath)); } return HelperXml.GetRows(results, stream, this.xmlExpandedPath, this.xmlSectionElementName, this.xmlRowElementName); }
/// <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 IEnumerable<DataRowValues> GetAllDataRowValues(RowAttribute[] rows, TestMethodInvokerContext invokerContext, HelperTestGridResults results) { Debug.Assert(rows != null, "rows != null"); Debug.Assert(invokerContext != null, "invokerContext != null"); Debug.Assert(results != null, "results != null"); if (rows.Length > 0) { Assembly testMethodAssembly = invokerContext.TestMethodInfo.DeclaringType.Assembly; // Process each RowAttribute, or derived attribute foreach (RowAttribute attr in rows) { // enumerate row data and invoke the test case with each yield they give us foreach (DataRowValues dataRowValues in attr.GetRowEnumerator(testMethodAssembly, results)) { if (attr.Ignore) { dataRowValues.Ignore = true; } yield return dataRowValues; } } } else { yield return new DataRowValues(); } }
/// <summary> /// Enumerate row data. /// Each row this attribute represents is yielded. /// </summary> /// <param name="resourceAssembly">The assembly containing the resource stream to use.</param> /// <param name="results">The helper to access param and formal arg type info.</param> /// <returns>An enumeration of DataRowValues to drive test method.</returns> public override IEnumerable<DataRowValues> GetRowEnumerator(Assembly resourceAssembly, HelperTestGridResults results) { Stream stream = resourceAssembly.GetManifestResourceStream(this.xmlResourceName); if (stream == null) { // List the valid resource names one could use in the error message, if desired string resourceList = string.Empty; if (this.listResourceNames) { resourceList = string.Format(" Valid resource names: {0}", string.Join(", ", resourceAssembly.GetManifestResourceNames())); } throw new FileNotFoundException(string.Format("The embedded resource '{0}' could not be found in the assembly '{1}'.{2}", this.xmlResourceName, resourceAssembly.FullName, resourceList)); } return HelperXml.GetRows(results, stream, this.xmlResourceName, this.xmlSectionElementName, this.xmlRowElementName); }
/// <summary> /// Enumerate row data. /// Each row this attribute represents is yielded. /// </summary> /// <param name="resourceAssembly">The assembly containing the resource stream to use. Used by derived row classes.</param> /// <param name="results">The helper to access param and formal arg type info. Used by derived row classes.</param> /// <returns>The data row values for this row to drive the test method.</returns> public virtual IEnumerable<DataRowValues> GetRowEnumerator(Assembly resourceAssembly, HelperTestGridResults results) { // The base RowAttribute just returns one row for any values it specifies // plus any metadata about the data row specified (Desc, Ignore, Defect, etc.). // Derived versions may open a data soruce and enumerate those. DataRowValues dataRowValues = new DataRowValues(); dataRowValues.Values = this.RowValues; dataRowValues.Desc = this.Desc; dataRowValues.Ignore = this.Ignore; dataRowValues.Defect = this.Defect; dataRowValues.Id = Convert.ToString(this.Id); dataRowValues.ExpectedException = this.ExpectedException; dataRowValues.Properties = this.RetrieveProperties(this.Properties); yield return dataRowValues; }
public override IEnumerable<DataRowValues> GetRowEnumerator(System.Reflection.Assembly resourceAssembly, HelperTestGridResults results) { for (int i = 0; i < 10; i++) { DataRowValues dataRowValues = new DataRowValues(); dataRowValues.Id = (i + 1).ToString(); dataRowValues.Values = new object[] {i}; yield return dataRowValues; } }