From: Manish A. <mag...@us...> - 2007-02-19 06:54:20
|
User: magrawal Date: 07/02/18 22:54:20 Modified: etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit AndroMDA.ScenarioUnit.csproj CodeAsserterAttribute.cs CodeDataProviderAttribute.cs IAsserter.cs IDataProvider.cs TestScenarioHelper.cs XMLAsserterAttribute.cs XMLDataProviderAttribute.cs Log: added documentation. Revision Changes Path 1.3 +2 -1 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit.csproj Index: AndroMDA.ScenarioUnit.csproj =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit.csproj,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -r1.2 -r1.3 --- AndroMDA.ScenarioUnit.csproj 14 Jan 2007 04:21:44 -0000 1.2 +++ AndroMDA.ScenarioUnit.csproj 19 Feb 2007 06:54:19 -0000 1.3 @@ -15,10 +15,11 @@ <DebugType>full</DebugType> <Optimize>false</Optimize> <OutputPath>bin\debug\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> + <DefineConstants>TRACE;DEBUG;w</DefineConstants> <ErrorReport>prompt</ErrorReport> <WarningLevel>4</WarningLevel> <PlatformTarget>AnyCPU</PlatformTarget> + <DocumentationFile>bin\debug\AndroMDA.ScenarioUnit.XML</DocumentationFile> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <DebugType>pdbonly</DebugType> 1.2 +81 -6 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/CodeAsserterAttribute.cs Index: CodeAsserterAttribute.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/CodeAsserterAttribute.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- CodeAsserterAttribute.cs 10 Jan 2007 22:56:52 -0000 1.1 +++ CodeAsserterAttribute.cs 19 Feb 2007 06:54:19 -0000 1.2 @@ -4,18 +4,93 @@ using System.Reflection; namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This is a concrete implementation of the <see cref="IAsserter"/> interface + /// that uses helper methods to assert actual output from a test case against expected output. + /// </summary> + /// <remarks> + /// This asserter is similar to the traditional mechanism of using + /// helper methods to separate out assertion logic from the main testing code. + /// <para> + /// This asserter is helpful when used in conjunction with <see cref="XmlAsserter"/> for return values/output parameters + /// that cannot be serialized into XML. + /// </para> + /// <para> + /// This class derives from the <c>System.Attribute</c> class. This + /// allows this class to be configured as the asserter for a test method return value or output parameter. + /// </para> + /// <para> + /// The AttributeUsage attribute for this class: + /// <c>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)]</c> + /// ensures that this attribute can be applied at a class, method or at a parameter level. + /// </para> + /// <para> + /// When this attribute is specified at a <c>TestFixture</c> level, + /// all the test method return values and output parameters in that <c>TestFixture</c> are asserted using this asserter + /// unless, if a different asserter is specified at a test method or parameter level. + /// When this asserter is specified as an attribute on the test method, it + /// overrides any asserter configured at the test fixture level. + /// Similarly, when specified at the return value or output parameter level, + /// this data provider is used to assert that parameter, irrespective of the asserter configured at the test method or test fixture levels. + /// </para> + /// </remarks> [AttributeUsage(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Parameter)] public class CodeAsserterAttribute : Attribute, IAsserter { private string _asserterMethodName; + + /// <summary> + /// This is an optional property to specify the name of the helper method that is called + /// to assert actual output against expected output. + /// </summary> + /// <remarks> + /// If this property is not set, a naiming convention is used to identify the method to be called. + /// The naming convention is: + /// <code escaped="true"> + /// [testMethodName_[parameterName]_assert() + /// </code> + /// <note> + /// In case of return values, there is no "parameterName" part in the naming convention. + /// </note> + /// </remarks> public string AsserterMethodName { get { return _asserterMethodName; } set { _asserterMethodName = value; } } + /// <summary> + /// This is the implementation of the <see cref="IAsserter"/> interface. + /// It uses a helper method to assert actual output against expected test output. + /// </summary> + /// <param name="outputObj">The object containing the actual test output</param> + /// <param name="pInfo">Meta information about the <paramref name="outputObj"/>.</param> + /// <param name="methodName">The name of the test method. This name is used to identify the helper assertion method using a naming convention.</param> + /// <param name="scenarioName">The name of the test scenario.</param> + /// <param name="testFixture">A reference to the object containing the helper method. + /// Usually, this is a reference to the TestFixture itself.</param> + /// <remarks> + /// If the <see cref="AsserterMethodName"/>property is not specified, this data provider uses a + /// naming convention to identify the helper method to + /// be called. + /// <para> + /// The naming convention used is: + /// </para> + ///<code escaped="true"> + /// [testMethodName]_[parameterName]_Assert() + /// </code> + /// <para> + /// The helper method must be a private instance method that has the following signature: + /// </para> + /// <code escaped="true" lang="c#"> + ///private void [testMethodName]_[parameterName]_Assert(object outputObj, ParameterInfo pInfo, string methodName, string scenarioName) + /// </code> + /// <note> + /// To assert return values, the "parameterName" part of the helper method name is ommited. + /// </note> + /// </remarks> public void AssertOutput(Object outputObj, ParameterInfo pInfo, string methodName, string scenarioName, object testFixture) { 1.3 +84 -0 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/CodeDataProviderAttribute.cs Index: CodeDataProviderAttribute.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/CodeDataProviderAttribute.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -r1.2 -r1.3 --- CodeDataProviderAttribute.cs 18 Jan 2007 10:49:48 -0000 1.2 +++ CodeDataProviderAttribute.cs 19 Feb 2007 06:54:19 -0000 1.3 @@ -4,18 +4,102 @@ using System.Reflection; namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This is a concrete implementation of the <see cref="IDataProvider"/> interface. + /// This data provider uses helper methods written in the TestFixture class + /// or a separate class to load input data for test cases. + /// </summary> + /// <remarks> + /// This data provider uses reflection ot execute a helper method + /// on an object reference to load the test data for a specific scenario. + /// This method of loading test data is almost the same as the mechanism used in + /// traditional unit testing where test data is separated out into helper methods. + /// This data provider is useful when used in conjunction with the + /// <see cref="XMLDataProvider"/> for input data types that cannot be serialized into XML + /// and therefore cannot be loaded using <see cref="XMlDataProvider"/>. + /// <para> + /// This class derives from the <c>System.Attribute</c> class. This + /// allows this class to be configured as a data provider for a test method parameter. + /// </para> + /// <para> + /// The AttributeUsage attribute for this class: + /// <c>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)]</c> + /// ensures that this attribute can be applied at a class, method or at a parameter level. + /// </para> + /// <para> + /// When this attribute is specified at a <c>TestFixture</c> level, + /// all the test method parameters in that <c>TestFixture</c> are loaded using this data provider + /// unless, if a different data provider is specified at a test method or parameter level. + /// When this data provider is specified as an attribute on the test method, it + /// overrides any data provider configured at the test fixture level. + /// Similarly, when specified at the parameter level, this data provider is used to load that parameter, irrespective of the data providers configured at the test method or test fixture levels. + /// </para> + /// </remarks> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)] public class CodeDataProviderAttribute : Attribute, IDataProvider { private string _dataMethodName; + + /// <summary> + /// This is an optional property that specifies the name of the helper method to be called by + /// this data provider to load input data. + /// </summary> + /// <remarks> + /// If this property is not specified, this data provider uses a + /// naming convention to identify the helper method to + /// be called. + /// <para> + /// The naming convention used is: + /// </para> + ///<code escaped="true"> + /// [testMethodName]_[parameterName]_data() + /// </code> + /// <para> + /// The helper method must be a private instance method that has the following signature: + /// </para> + /// <code escaped="true" lang="c#"> + /// private object [testMethodName]_[parameterName]_data(ParameterInfo pinfo, string methodName, string scenarioName) + /// </code> + /// </remarks> public string DataMethodName { get { return _dataMethodName; } set { _dataMethodName = value; } } + /// <summary> + /// This is the implementation of the <see cref="IDataProvider"/> interface. + /// This implementation uses reflection to invoke a helper method on an object reference to load input data + /// for a test scenario. + /// </summary> + /// <param name="pInfo">Meta information about the input parameter to be loaded.</param> + /// <param name="methodName">The name of the test method whose input parameter needs to be loaded. + /// This name is used in a naming convention to identify the helper method to be + /// called to load the input data.</param> + /// <param name="scenarioName">The name of the test scenario for which test input data needs to be loaded. + /// This name is passed to the helper method that returns input data.</param> + /// <param name="testFixture">This is the object reference that contains the helper method that returns input data. + /// Usually, this is a reference to the TestFixture itself.</param> + /// <returns>Returns the loaded input data as returned from the helper method.</returns> + /// <remarks> + /// If the <see cref="DataMethodName"/>property is not specified, this data provider uses a + /// naming convention to identify the helper method to + /// be called. + /// <para> + /// The naming convention used is: + /// </para> + ///<code escaped="true"> + /// [testMethodName]_[parameterName]_data() + /// </code> + /// <para> + /// The helper method must be a private instance method that has the following signature: + /// </para> + /// <code escaped="true" lang="c#"> + /// private object [testMethodName]_[parameterName]_data(ParameterInfo pinfo, string methodName, string scenarioName) + /// </code> + /// </remarks> public object GetData(ParameterInfo pInfo, string methodName, string scenarioName, object testFixture) { if (string.IsNullOrEmpty(DataMethodName)) 1.2 +48 -0 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/IAsserter.cs Index: IAsserter.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/IAsserter.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- IAsserter.cs 10 Jan 2007 22:56:52 -0000 1.1 +++ IAsserter.cs 19 Feb 2007 06:54:19 -0000 1.2 @@ -3,8 +3,56 @@ namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This interface is implemented by all concrete Asserter classes. + /// The implementation of this interface provides the ability to assert that actual output is equal to expected output for a specific test scenario. + /// </summary> + /// <remarks> + /// The implementation of this interface receives the actual output returned + /// by invoking the system under test for a specific scenario + /// and compares this output with expected data stored outside the actual test cases (Similar to the data provider concept.) + /// <para> + /// A concrete asserter that implements this interface needs to + /// derive from the <see cref="System.Attribute"/> class so that it can + /// be configured to be used to assert output data. + /// <para> + /// The asserter should use the following<c>AttributeUsage</c> tag: + /// <para> + /// <c>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)]</c> + /// </para> + /// This allows an asserter to be configured at a <c>TestFixture</c>, + /// <c>TestMethod</c>, or a <c>parameter</c> level, giving fine grained control to + /// the developers writing unit tests over how test output is asserted. + /// </para> + /// </para> + /// </remarks> public interface IAsserter { + /// <summary> + /// This method asserts actual output for a specific test scenario + /// with expected output. + /// The <see cref="TestScenarioHelper"/> class calls this method + /// once for each return and output paramter + /// of a test method. + /// </summary> + /// <param name="outputObj">The actual output obtained by invoking the system under test.</param> + /// <param name="pInfo">Meta information about the actual output object. + /// This information can be used by concrete IAsserter implementations to help load the expected output and perform + /// the comparison of actual output with expected output.</param> + /// <param name="methodName">This is the name of the test method being used to invoke the functionality under test. + /// This information can be used by concrete IAsserter implementations to help load the expected output and perform + /// the comparison of actual output with expected output.</param> + /// <param name="scenarioName">The name of the test scenario being executed. + /// This information can be used by concrete IAsserter implementations to help load the expected output and perform + /// the comparison of actual output with expected output.</param> + /// <param name="testFixture">A reference to the class containing the test case or any other helper methods + /// that can help in asserting the output.</param> + /// <remarks> + /// This method receives only the actual output as a parameter + /// and not the expected output because the concrete asserter + /// is required to load/find the expected output on its own using concepts similar to the data provider. + /// Meta information about the output, test method and the test scenario being executed is passed along to this method. + /// </remarks> void AssertOutput(Object outputObj, ParameterInfo pInfo, string methodName, string scenarioName, object testFixture); } } 1.2 +39 -0 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/IDataProvider.cs Index: IDataProvider.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/IDataProvider.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- IDataProvider.cs 10 Jan 2007 22:56:52 -0000 1.1 +++ IDataProvider.cs 19 Feb 2007 06:54:19 -0000 1.2 @@ -5,8 +5,47 @@ namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This is the interface implemented by all data providers. + /// </summary> + /// <remarks> + /// A data provider is used by the <see cref="TestScenarioHelper"/> class to load the input data for + /// a test scenario and pass it to a test method. + /// <para> + /// A data provider that implements this interface needs to + /// derive from the <see cref="System.Attribute"/> class so that it can + /// be configured to be used to read input data. + /// <para> + /// The data provider should use the following<c>AttributeUsage</c> tag: + /// <para> + /// <c>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)]</c> + /// </para> + /// This allows a data provider to be configured at a <c>TestFixture</c>, + /// <c>TestMethod</c>, or a <c>parameter</c> level, giving fine grained control to + /// the developers writing unit tests over how test input data is provided for each test case. + /// </para> + /// </para> + /// </remarks> public interface IDataProvider { + /// <summary> + /// <c>TestScenarioHelper</c> calls this method on a concrete implementation of + /// this interface once for each input parameter for a test method. + /// </summary> + /// <param name="pInfo">This is the <c>System.Reflection.ParameterInfo</c> object that contains information about the + /// input parameter to be loaded.</param> + /// <param name="methodName">This is the name of the test method to which the loaded input parameter will be passed. + /// The XML and code-based data providers use this name as a part of of a naming convention to locate the source of input data.</param> + /// <param name="scenarioName">This is the name of the test scenario for which input data needs to be loaded. + /// The XML and code-based concrete data provider implementations use this scenario name as a part of a naming convention to locate the + /// source of input data.</param> + /// <param name="testFixture">This is a reference to an object that contains any helper methods or information that may be needed by a specific data provider. + /// For example, in case of code-based data provider, this object contains the helper method that will return the loaded input parameters.</param> + /// <returns>This method returns the loaded input test method parameter as an object.</returns> + /// <remarks> + /// This method is called by <see cref="TestScenarioHelper"/> on a concrete implementation + /// of this interface for each input parameter of a test method. + /// </remarks> object GetData(ParameterInfo pInfo, string methodName, string scenarioName, object testFixture); } } \ No newline at end of file 1.2 +70 -27 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/TestScenarioHelper.cs Index: TestScenarioHelper.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/TestScenarioHelper.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- TestScenarioHelper.cs 10 Jan 2007 22:56:52 -0000 1.1 +++ TestScenarioHelper.cs 19 Feb 2007 06:54:19 -0000 1.2 @@ -4,33 +4,75 @@ using System.Text; using System.Reflection; + +///<summary> +///This namespace contains the various classes for the AndroMDA.ScenarioUnit library. +///</summary> namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This is the helper class that is used to invoke the functionality provided by the AndroMDA.ScenarioUnit framework. + /// </summary> + /// <remarks> + /// This class has a single public static method + /// <c>Invoke()</c> that is called from test cases to execute a specific test scenario. + /// <para> + /// To be able to use this testing framework, the following + /// configuration entries are required + /// in the app.config file of the test harness: + /// <code escaped="true"> + /// <runtime> + /// <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + ///<dependentAssembly> + ///<assemblyIdentity name="nunit.framework" publicKeyToken="96d09a1eb7f44a77" culture="Neutral" /> + ///<bindingRedirect oldVersion="2.0.6.0" newVersion="2.2.8.0" /> + ///<bindingRedirect oldVersion="2.1.4.0" newVersion="2.2.8.0" /> + ///<bindingRedirect oldVersion="2.2.0.0" newVersion="2.2.8.0" /> + /// </dependentAssembly> + ///</assemblyBinding> + ///</runtime> + /// </code> + /// </para> + /// <note> + /// The "NewVersion" value in these entries should be the value of the + /// NUnit version being used in the test harness. + /// </note> + /// <para> + /// Look at the MoneyServiceSample in the samples folder of the + /// AndroMDA.ScenarioUnit source to see examples of simple usage of this test framework. + /// </para> + /// <para> + /// To see samples of all possible combinations in which this testing framework can be used, + /// look at the test cases implemented for this framework itself + /// in the AndroMDA.ScenarioUnit.Tests project. + /// </para> + /// </remarks> public class TestScenarioHelper { + + protected TestScenarioHelper() { } + /// <summary> - /// The only public method of this class. - /// this is called from test cases and does the following. - /// Calls the method specified by the "methodName" attribute; - /// passing in all input parameters after reading them from XML files on the disk. - /// The following convention is used to determine the file name for reading in a parameter: - /// methodName_scenarioName[_parameterName].xml - /// The parameterName part is not present for files corresponding to the returned value from a method. - /// The value returned from the method call, if any, is saved in XML format to - /// a file. - /// Next, for all output parameters and return values, assertions are performed by using the expected output XML files. These files are also loaded - /// based on the naming convention specified above. - /// Before comparing the actual and expected XML files, this method performs cleanup on the - /// two XML documents and removes the nodes specified in the "rules" XML file. - /// These are nodes like generated identifiers, date time fields etc. that cannot be specified in the expected output because these are determined at run time. - /// The location of the four sets of files used in this process is specified by using the - /// TestDataInputDir, TestDataExpectedOutputDir, TestDataActualOutputDir, and TestDataRulesDir key-value - /// pairs in the configuration file of the test harness. + /// This is the method used to invoke a test method for a specific scenario. /// </summary> /// <param name="methodName">The test method to execute. This must be a private instance method /// in the TestFixture class.</param> /// <param name="scenarioName">The test scenario.</param> /// <param name="testFixture">The class containing the test method.</param> + /// <remarks> + /// this method is called from an NUnit test case and does the following: + /// <list type="bullet"> + /// <item> + /// Calls the method specified by the <c>methodName</c> parameter; + /// passing in all input parameters by using the concrete implementation of <see cref="IDataProvider"/> configured for each parameter. + /// </item> + /// <item> + /// Captures the actual output returned from the test method and + /// compares it with the expected output using the concrete implementation of <see cref="IAsserter"/> configured for each return value + /// and out/ref parameter. + /// </item> + /// </list> + /// </remarks> public static void Invoke(string methodName, string scenarioName, Object testFixture) { MethodInfo mInfo = testFixture.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.IgnoreCase); @@ -41,8 +83,8 @@ foreach (ParameterInfo pInfo in pInfos) { Object parameter = null; - //Try to load a parameter from an XML - //file only if it is an input parameter. + //Try to load a parameter + //only if it is an input parameter. //Otherwise, just add the parameterInfo for that parameter //into an array for assertion later. if (pInfo.IsOut) @@ -95,6 +137,7 @@ throw e.InnerException; } } + #region private helper methods /// <summary> /// Helper method to get the asserter to be used for a test case. 1.4 +196 -0 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/XMLAsserterAttribute.cs Index: XMLAsserterAttribute.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/XMLAsserterAttribute.cs,v retrieving revision 1.3 retrieving revision 1.4 diff -u -w -r1.3 -r1.4 --- XMLAsserterAttribute.cs 18 Jan 2007 10:49:48 -0000 1.3 +++ XMLAsserterAttribute.cs 19 Feb 2007 06:54:19 -0000 1.4 @@ -12,6 +12,72 @@ namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This is a concrete implementation of the <see cref="IAsserter"/> interface that uses XML files to store and compare expected output + /// with actual output objects serialized into XML. + /// </summary> + /// <remarks> + /// This asserter uses XML asserts to compare actual and expected output from a test scenario. + /// Internally, it uses an open source XML-based unit testing framework called + /// NXUnit <see ref="http://www.sf.net/NXUnit"/> to perform the XML comparisons. + /// <para> + /// Similar to the <see cref="XMLDataProvider"/>, this asserter also uses the + /// XML format produced by serializing an object using the System.Xml.Serialization.XmlSerializer class. + /// This means that this asserter can be used to assert only those return/output types + /// that can be serialized into XML. + /// </para> + /// <para> + /// The <see cref="TestScenarioHelper"/> class constructs a concrete instance of this asserter + /// for each return value/output parameter that is configured to use this asserter for a test method. + /// </para> + /// <para> + /// The following 3 entries are required in the + /// test harness app.config file to use this asserter: + /// </para> + /// <para> + /// <code escaped="true"> + /// <appSettings> + /// <add key="TestDataExpectedOutputDir" value="../../testdata/expected_output"/> + ///<add key="TestDataActualOutputDir" value="../../testdata/actual_output"/> + ///<add key="TestDataRulesDir" value="../../testdata/rules"/> + ///</appSettings> + /// + /// </code> + /// </para> + /// <para> + /// These 3 entries specify the folders that store the following: + /// <list type="bullet"> + /// <item>expected output as serialized XML</item> + /// <item>actual output generated by executing a test case</item> + /// <item>XML comparison rules for ignoring the values that cannot be compared between actual and expected output, e.g. database generated IDs etc. (more details below)</item> + /// </list> + /// </para> + /// <para> + /// This asserter provides the ability to ignore parts of the output while comparing actual and expected values. + /// This is required for values that cannot be predicted and cannot be a part of the expected output, such as + /// a date time field that stores the current date/time value or an ID field that is generated in the database. + /// Rules can be created to ignore such items while asserting actual and expected outputs. These rules + /// take the form of XPath queries that specify exact nodes in the serialized XML object to be compared. + /// </para> + /// <para> + /// This class derives from the <c>System.Attribute</c> class. This + /// allows this class to be configured as the asserter for a test method return value or output parameter. + /// </para> + /// <para> + /// The AttributeUsage attribute for this class: + /// <c>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)]</c> + /// ensures that this attribute can be applied at a class, method or at a parameter level. + /// </para> + /// <para> + /// When this attribute is specified at a <c>TestFixture</c> level, + /// all the test method return values and output parameters in that <c>TestFixture</c> are asserted using this asserter + /// unless, if a different asserter is specified at a test method or parameter level. + /// When this asserter is specified as an attribute on the test method, it + /// overrides any asserter configured at the test fixture level. + /// Similarly, when specified at the return value or output parameter level, + /// this data provider is used to assert that parameter, irrespective of the asserter configured at the test method or test fixture levels. + /// </para> + /// </remarks> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)] public class XMLAsserterAttribute : Attribute, IAsserter @@ -21,6 +87,27 @@ private string _expectedOutputDir; private string _rulesDir; + /// <summary> + /// This property is used in conjunction with the + /// configuration entry + /// <code escaped="true"> + /// <add key="TestDataActualOutputDir" value="[somePath]"/> + /// </code> + /// <para> + /// This configuration entry specifies the directory in which all + /// actual output is dumped as serialized XML. + /// This property is used to specify a sub-directory below the TestDataActualOutputDir + /// folder. + /// </para> + /// </summary> + /// <remarks> + /// This property helps organize test output data in + /// sub-folders below the TestDataActualOutputDir folder. + /// <para> + /// This property is optional and if it is not + /// set, the methods in this class will output all actual output in the TestDataActualOutputDir folder. + /// </para> + /// </remarks> public string ActualOutputDir { get @@ -35,6 +122,27 @@ set { _actualOutputDir = value; } } + /// <summary> + /// This property is used in conjunction with the + /// configuration entry + /// <code escaped="true"> + /// <add key="TestDataExpectedOutputDir" value="[somePath]"/> + /// </code> + /// <para> + /// This configuration entry specifies the directory in which + /// expected test output is stored as serialized XML. + /// This property is used to specify a sub-directory below the TestDataExpectedOutputDir + /// folder. + /// </para> + /// </summary> + /// <remarks> + /// This property helps organize expected test output data in + /// sub-folders below the TestDataExpectedOutputDir folder. + /// <para> + /// This property is optional and if it is not + /// set, the methods in this class will look for expected test output in the TestDataExpectedOutputDir folder. + /// </para> + /// </remarks> public string ExpectedOutputDir { get @@ -49,6 +157,29 @@ set { _expectedOutputDir = value; } } + /// <summary> + /// This property is used in conjunction with the + /// configuration entry + /// <code escaped="true"> + /// <add key="TestDataRulesDir" value="[somePath]"/> + /// </code> + /// <para> + /// This configuration entry specifies the directory in which + /// XML comparison rules are stored as XPath queries. These XPath queries specify the parts of actual and expected output + /// XML files that do not need to be compared while asserting actual output against expected output. + /// This property is used to specify a sub-directory below the TestDataRulesDir + /// folder. + /// </para> + /// </summary> + /// <remarks> + /// This property helps organize test assertion rules in + /// sub-folders below the TestDataRulesDir folder. + /// <para> + /// This property is optional and if it is not + /// set, the methods in this class will look for assertion ignore rules + /// in the TestDataRulesDir folder. + /// </para> + /// </remarks> public string RulesDir { get @@ -65,6 +196,71 @@ #endregion #region interface implementation + /// <summary> + /// This method implements the <see cref="IAsserter"/> interface. + /// In this implementation, actual and expected output is serialized as XML + /// and then compared using an open source XML-based framework named NXUnit + /// <see ref="http://www.sf.net/NXUnit"/>. + /// </summary> + /// <param name="outputObj">The actual output returned from the system under test.</param> + /// <param name="pInfo">Meta information about the <paramref name="outputObj"/> object.</param> + /// <param name="methodName">The name of the test method. + /// This name is used as a part of file naming convention used to name actual output, expected output and rules XML files.</param> + /// <param name="scenarioName"> + /// The name of the test scenario. + /// This name is used as a part of file naming convention used to name actual output, expected output and rules XML files. + /// </param> + /// <param name="testFixture">This parameter is not used by this asserter.</param> + /// <remarks> + /// This method is called by the <see cref="TestScenarioHelper"/> class once for + /// every return value/output parameter of a test method for which + /// this asserter is configured. + /// <para> + /// This method serializes the actual test output returned from the + /// system under test using the System.Xml.Serialization.XmlSerializer class. + /// </para> + /// <para> + /// This method also saves the actual output to a physical file, so that it + /// can be reviewed manually after the test case is run. This file is created in the folder + /// specified by the <see cref="ActualOutputDir"/> property. + /// </para> + /// <para> + /// The name of the physical file is created using the same naming convention as that used + /// by the <see cref="XMLDataProvider"/> class: methodName_scenarioName_parameterName.xml. + /// <note> + /// In case of return parameters, there is no "parameterName", so, the file name is just methodName_scenarioName.xml. + /// </note> + /// </para> + /// <para> + /// This method reads expected output from XML files from the location + /// specified by the <see cref="ExpectedOutputDir"/> property. + /// </para> + /// <para> + /// The file naming convention used to identify the file to be read is the same here as well: + /// methodName_scenarioName_parameterName.xml. + /// </para> + /// <para> + /// Not all values in actual and expected output can be compared + /// in some situations. + /// </para> + /// <para> + /// For example, the output may contain a generated ID from the database + /// or a dateTime field that is filled with the current + /// date time value by the system under test. + /// </para> + /// <para> + /// Such parts that cannot be compared need to be ignored while + /// asserting the actual output against expected output. This can be done by creating a rules + /// file for the specific return value/output parameter for each test scenario. + /// </para> + /// <para> + /// This rules file takes the form of an XML file + /// with XPath queries identifying the nodes in the actual and expected + /// output XML files that need to be ignored. This rules file also + /// follows the same naming convention of methodName_scenarioName_parameterName.xml + /// and is placed in the directory specified by the <see cref="RulesDir"/> property. + /// </para> + /// </remarks> public void AssertOutput(Object outputObj, ParameterInfo pInfo, string methodName, string scenarioName, object testFixture) { SaveOutput(outputObj, pInfo, methodName, scenarioName); 1.3 +134 -0 plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/XMLDataProviderAttribute.cs Index: XMLDataProviderAttribute.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.ScenarioUnit/AndroMDA.ScenarioUnit/XMLDataProviderAttribute.cs,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -r1.2 -r1.3 --- XMLDataProviderAttribute.cs 18 Jan 2007 10:49:48 -0000 1.2 +++ XMLDataProviderAttribute.cs 19 Feb 2007 06:54:19 -0000 1.3 @@ -10,6 +10,42 @@ namespace AndroMDA.ScenarioUnit { + /// <summary> + /// This is a concrete implementation of the <see cref="IDataProvider"/> interface. + /// This data provider loads input data stored as serialized XML objects in files. + /// </summary> + /// <remarks> + /// To use this data provider, the following configuration entry is required in the configuration file of the test harness: + /// <para> + /// <code escaped="true"> + /// <add key="TestDataInputDir" value="[somePath]" /> + /// </code> + /// </para> + /// <para> + /// This entry specifies the path where all the input + /// XML files are located. + /// <note> + /// A path relative to the test harness assembly binary (usually located in testHarness/bin/debug) can be specified for this configuration entry. + /// </note> + /// </para> + /// <para> + /// This class derives from the <c>System.Attribute</c> class. This + /// allows this class to be configured as a data provider for a test method parameter. + /// </para> + /// <para> + /// The AttributeUsage attribute for this class: + /// <c>[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)]</c> + /// ensures that this attribute can be applied at a class, method or at a parameter level. + /// </para> + /// <para> + /// When this attribute is specified at a <c>TestFixture</c> level, + /// all the test method parameters in that <c>TestFixture</c> are loaded using this data provider + /// unless, if a different data provider is specified at a test method or parameter level. + /// When this data provider is specified as an attribute on the test method, it + /// overrides any data provider configured at the test fixture level. + /// Similarly, when specified at the parameter level, this data provider is used to load that parameter, irrespective of the data providers configured at the test method or test fixture levels. + /// </para> + /// </remarks> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Parameter)] public class XMLDataProviderAttribute : Attribute, IDataProvider @@ -17,6 +53,24 @@ #region member variables and properties. private string _inputDir; + /// <summary> + /// This property is used in conjunction with the + /// configuration entry + /// <code escaped="true"> + /// <add key="TestDataInputDir" value="[some path]"> + /// </code> + /// This configuration entry specifies the directory that contains all input data XML files. + /// This property is used to specify a sub-directory below the TestDataInputDir + /// folder that will be used to load the input data. + /// </summary> + /// <remarks> + /// This property helps organize test input data in + /// sub-folders below the TestDataInputDir folder. + /// <para> + /// This property is optional and if it is not + /// set, the methods in this class will look for test input XML files in the TestDataInputDir folder. + /// </para> + /// </remarks> public string InputDir { get @@ -33,6 +87,86 @@ #endregion #region public methods + /// <summary> + /// This is the concrete implementation of the + /// <see cref="IDataProvider"/> interface. + /// This method loads an input parameter for a test method for a specific scenario from an XML file. + /// </summary> + /// <param name="pInfo">This is the <c>System.Reflection.ParameterInfo</c> object that contains information about the + /// input parameter to be loaded.</param> + /// <param name="methodName">This is the name of the test method to which the loaded input parameter will be passed. + /// This data provider uses this methodName value as a part of a naming convention to locate the XML file that contains input data. + /// The input XML file is named using the convention [methodName_scenarioName_parameterName.xml] </param> + /// <param name="scenarioName">This is the name of the test scenario for which input data needs to be loaded. + /// This data provider uses the scenarioName value as a part of a naming convention to locate the XML file that contains input data. + /// The input XML file is named using the convention [methodName_scenarioName_parameterName.xml] </param> + /// <param name="testFixture">This parameter is not currently used by this data provider. </param> + /// <returns>This method returns the loaded input test method parameter as an object.</returns> + /// <remarks> + /// The input data is stored as serialized XML for the object to be loaded. + /// The XML schema used is the one generated by serializing the object using <c>System.Xml.Serialization.XmlSerializer</c>. + /// This method uses a convention to locate the XML file to be read to load and return the object. + /// <para> + /// The XML file name is constructed using the three parameters <paramref name="pInfo"/>, <paramref name="methodName"/>, and <paramref name="scenarioName"/>. + /// The file name is assumed to be : + /// <para> + /// methodName_scenarioName_parameterName.xml + /// </para> + /// For example, to load the input parameters for the test method <c>private Money Add(Money m1, Money m2)</c> + /// for the following invokation: <c>TestScenarioHelper.Invoke("Add", "SimpleAdd", this)</c> + /// this method will look for the files Add_SimpleAdd_m1.xml and + /// Add_SimpleAdd_m2.xml in the <see cref="XMLDataProvider.InputDir"/> directory. + /// </para> + /// <note> + /// you can use code similar to the following to generate the first XML file for an object and then copy it + /// over and over for multiple scenarios replacing specific values according to the input scenario. + /// <para> + /// <code lang="c#"> + /// Money m1 = new Money(1, "USD"); + /// XMLSerializer xs = new XMLSerializer(typeof(Money)); + /// using (StreamWriter sw = new StreamWriter(File.OpenWrite("Add_SimpleAdd_m1.xml"))) + /// { + /// xs.Serialize(sw, m1); + /// } + /// </code> + /// </para> + /// </note> + /// <note> + /// While trying to read polymorphic objects, + /// i.e. trying to read a derived object while the input parameter is of the base type, + /// make sure that the base type definition has an <c>[XMLInclude()]</c> attribute refering to the derived type. + /// </note> + /// </remarks> + /// <example> + /// This example shows the serialized form of the following Money class: + /// <code lang="c#"> + /// + /// namespace MoneyServiceSample + ///{ + /// public class Money + /// { + /// public int amount; + /// public string currency; + /// public Money() { } + /// + /// public Money(int amt, string crncy) + /// { + /// amount = amt; + /// currency = crncy; + /// } + /// } + ///} + /// + /// </code> + /// The following is the Add_SimpleAdd_m1.xml file: + /// <code escaped="true"> + /// <?xml version="1.0" encoding="utf-8"?> + ///<Money xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + /// <amount>12</amount> + /// <currency>CHF</currency> + ///</Money> + /// </code> + /// </example> public object GetData(ParameterInfo pInfo, string methodName, string scenarioName, object testFixture) { string inputFileName = GetFileName(pInfo, methodName, scenarioName); |