MSDN Magazine Launch Issue - February 15, 2008 - (Page 75) Figure 15 LoggingTestService Class namespace UnitTesting.Samples { public class LoggingTestService : DatabaseTestService { public override ExecutionResult[] Execute( ConnectionContext scriptExecutionContext, ConnectionContext privilegedExecutionContext, DatabaseTestAction action, params System.Data.Common.DbParameter[] sqlParameters) { // Execute the test ExecutionResult[] results = base.Execute( scriptExecutionContext, privilegedExecutionContext, action, sqlParameters); } return results; } } deserializes the empty DataSet that represents the expected data tables (and their columns) and compares them with the DataSet generated by the test. Modifying Test Execution The default behavior for connection strings, database deployment, and test execution is accessed through the instance of the DatabaseTestService class that is registered on the static TestService property on the DatabaseTestClass. The methods on the DatabaseTestService class are marked as virtual so that they can be overridden individually or all together to change how tests are executed. You might want to modify the default behavior if, Figure 16 Execute Implementation public override ExecutionResult[] Execute( ConnectionContext scriptExecutionContext, ConnectionContext privilegedExecutionContext, DatabaseTestAction action, params System.Data.Common.DbParameter[] sqlParameters) { // We want to evaluate the conditions ourselves so that we // can log the results from every test’s execution List conditions = new List (); if (action != null) { conditions.AddRange(action.Conditions); action.Conditions.Clear(); } // Execute the test ExecutionResult[] results = base.Execute( scriptExecutionContext, privilegedExecutionContext, action, sqlParameters); // Verify and log the results bool verificationFailed = false; try { foreach (TestCondition condition in conditions) { if (condition.Enabled) { condition.Assert(privilegedExecutionContext.Connection, results); } } for example, you’re using a custom connection string encryption/ decryption mechanism, you’re modifying the way database deployment or data generation is performed, or you’re automatically logging execution results. Each of these modifications (and more) can be achieved by writing your own test service class and then registering that test service with the harness so that it can be used during test execution. In this sample, I’m going to write a test service that will log the results of a test execution to a file using DataSet serialization. The service can be configured to log no results, all results, or only failed results. This simple service makes it easy to see the result of your tests’ execution within the harness. First, I define the class; I am simply modifying the way tests are executed, so the class looks like that in Figure 15. As you can see, the LoggingTestService subclasses the DatabaseTestService class and then overrides the Execute method. Next, I need to add results logging. Note that the default implementation of Execute executes the test script and then evaluates the test conditions; this implementation will not meet my needs, however, because I don’t have access to the execution results in the event of verification failure. Therefore, to meet my goals, I’ll instead evaluate the assigned test conditions after calling the base Execute method and then log the results accordingly. The complete Execute implementation looks like Figure 16. This implementation still uses the base Execute implementation, but, afterward, it verifies the results using the action’s test conditions and writes the results of that execution to a file. I’m using a GUID to generate a unique name because this method will be called multiple times during a single test’s execution. It is also im- } catch { verificationFailed = true; throw; } finally { if (results != null && (Verbosity == LogVerbosity.AllResults || (verificationFailed && Verbosity == LogVerbosity.OnlyFailure))) { // Serialize the dataset to an .xml file to be visualized string resultPrefix = Guid.NewGuid().ToString(“N”); for (int resultIndex = 0; resultIndex < results.Length; resultIndex++) { string dsFilePath = Path.GetFullPath(string.Format( CultureInfo.CurrentCulture, “{0}-{1}.xml”, resultPrefix, resultIndex)); ExecutionResult result = results[resultIndex]; result.DataSet.WriteXml(dsFilePath, System.Data.XmlWriteMode.IgnoreSchema); } Trace.TraceInformation(“Log {0} {1}”, resultIndex, dsFilePath); } } } return results; Database Unit Testing launch2008 75
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.