MSDN Magazine Launch Issue - February 15, 2008 - (Page 74) Figure 13 Defining Editor Style namespace UnitTesting.Samples.TestConditions.Design { class DataSetEditor : UITypeEditor { public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) { return UITypeEditorEditStyle.Modal; } public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { MessageBox.Show(“DataSetEditor::EditValue”); return value; } system.drawing.design.uitypeeditor) and the EditorAttribute (msdn2.microsoft.com/system.componentmodel.editorattribute) enable the component in the .NET Framework. The UITypeEditor (msdn2.microsoft.com/ developer to design a custom editing experience and assign that experience (through the EditorAttribute) to a component property that is designed in the IDE. In this case, I want the experience to be a modal dialog so I define the editor as in Figure 13. Since both test conditions are configured the same way, I define the property on the base class: [DesignOnly(true)] [Editor( typeof(UnitTesting.Samples.TestConditions.Design.DataSetEditor), typeof(System.Drawing.Design.UITypeEditor))] public string Configuration { get { return “Press to configure”; } set { } } } } If you want to run the script as a separate .bat file, modify the first three lines to retrieve values from environment variables (instead of MSBuild variables). After this initial setup has been completed, I can see the two new conditions in the test conditions dropdown. I added the DisplayNameAttribute (msdn2.microsoft.com/system.componentmodel.displaynameattribute) to the test conditions so they appear as Checksum and Expectedschema. Now that I have finished setup, I need to develop the test conditions’ design-time experience so that the user can click on the ellipses in the property browser and configure the condition instance. If you have designed components for Windows Forms in Visual Studio, then you are probably already familiar with the UITypeEditor Figure 14 EditValue Method public override object EditValue( ITypeDescriptorContext context, IServiceProvider provider, object value) { IUIService uiService = (IUIService)provider .GetService(typeof(IUIService)); DataSetTestCondition cond = context.Instance as DataSetTestCondition; if (uiService != null && cond != null) { DataSetSelectorDialog dsDialog = new DataSetSelectorDialog(); if (cond.Site != null) { dsDialog.Text = string.Format(CultureInfo.CurrentCulture, “Configuration for {0}”, cond.Site.Name); } dsDialog.Query = cond.GetTestScript(); dsDialog.StartPosition = FormStartPosition.CenterParent; if (uiService.ShowDialog(dsDialog) == DialogResult.OK) { value = dsDialog.Query; if (cond != null) { cond.ConfigureExpectedDataSet(dsDialog.Result); } } } } return value; When I compile and deploy the test conditions, I see the Configuration property, and when I click on the ellipses, the message box displays. At this point, all the code needed to integrate with Visual Studio has been completed and I can concentrate on the logic of the test conditions themselves. First I create a form—this will be displayed by the DataSetEditor I just created—that allows the user to configure the DataSet expected by the test condition. This form (named DataSetSelectorDialog) is seeded with the T-SQL from the test and allows the user to execute that T-SQL against a target server in order to preview the data prior to configuring the test condition. Once the user is happy with the DataSet, he can click OK on the dialog, signaling that the test condition should use the DataSet and return control to the editor. Next, I modify the editor to display and process the form’s content after the user clicks OK. Normally, a UI editor passes back the value that should be stored in the property being edited, but in this case I want the property to display the “Press here to configure” text and pass back the DataSet to the edited test condition. Since the conditions would process the DataSet differently, I define a virtual method on the base class and have the editor call this method to set the DataSet instance; the derived classes override the method to add their specific implementation. With these changes the EditValue method now looks like Figure 14. There, I retrieve the IUIService to display a modal dialog; this service integrates the display of the modal dialog with the rest of the Visual Studio windowing behavior. Now that you’ve seen the design-time behavior of the test conditions, let’s see what happens when the test script is executed against the target server and the results of that execution are collected inside a DataSet. After the test is executed, an instance of the ExecutionResult class is created and populated with information about the test’s execution (including the DataSet). The test harness then loops through all test conditions that have been configured to verify the execution results and calls the Assert method on each test condition to verify those results. In the case of the test conditions in this example, they retrieve the DataSet from the first ExpectedResult in the results array, and then ChecksumCondition generates a hash of the actual DataSet and compares that hash with the hash generated during design time. ExpectedSchemaCondition 74 msdnmagazine Database Unit Testing http://msdn2.microsoft.com/system.drawing.design.uitypeeditor http://msdn2.microsoft.com/system.drawing.design.uitypeeditor http://msdn2.microsoft.com/system.componentmodel.editorattribute http://msdn2.microsoft.com/system.componentmodel.editorattribute http://msdn2.microsoft.com/system.componentmodel.displaynameattribute http://msdn2.microsoft.com/system.componentmodel.displaynameattribute
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.