I haven't posted a lot in the last few weeks, and there's a succinct reason for that. In fact, I can name it in three words: Full Test Pass.
The concept is close to what it sounds like. During the earlier stages of product planning, the test team for ASP.NET and the web development profile for Visual Studio used the time to plan its test coverage. In total, we wrote descriptions of over 40,000 test cases that we wanted to run. In the span of about four weeks ending earlier this month, we took the time to acutally execute nearly all of them, many for the first time.
Don't take that to mean that we whittled away all the hours between whiles drinking beverages and playing foosball -- we are professionals, after all. We used the time to automate a large subset of our tests, including our acceptance tests (tests that we run on each daily build of the product to get a rough sense of its quality and catch really the big bugs). Automation infrastructure -- the libraries and components our testcases use to simplify automation and manage the process of reporting results to our testcase management database (named Mad Dog, if you can believe it) -- also took up a lot of time.
But 40,000 is a big number, and in that number were a lot of scenarios that we just hadn't tried yet. For example, one of the features I own is Control Designers, which is the mechanism a custom control developer uses to control the appearance and behavior of her control in Visual Studio's web design environment. As part of this, I test several new host services that are exposed by Visual Studio which the authors of Control Designers can use to simplify their work. One of these is an interface with the name IWebFormsBuilderUIService, which exposes methods for creating common UI dialogs, among them a URL editor. In Visual Basic .NET, the code a control author would need to write in order to use this would be something like this:
Imports System.ComponentModelImports System.ComponentModel.DesignImports System.Web.UI.DesignImports System.Web.UIImports System <Designer(GetType(ExampleControlDesigner)), . . . > Public Class ExampleControl Inherits System.Web.UI.WebControls.WebControl Dim _url As String <Bindable(True), Category("Appearance"), DefaultValue("")> Property URL() As String Get Return _url End Get Set(ByVal Value As String) _url = Value End Set End Property . . .End Class Public Class ExampleControlDesigner Inherits ControlDesigner Protected Overrides Sub OnClick(ByVal e As DesignerRegionEventArgs) Dim iwfbuis as IWebFormsBuilderUIService Dim ctl As ExampleControl Mybase.OnClick(e) ctl = Component iwfbuis = GetService(GetType(IWebFormsBuilderUIService)) try ctl.URL = iwfbuis.BuildUrl(Nothing, ctl.URL, RootDesigner.DocumentUrl, "Please Choose a URL", "", UrlBuilderOptions.None) catch ex as exception Msgbox(ex.Message) end try UpdateDesignTimeHtml() End Sub . . .End Class
Imports System.ComponentModelImports System.ComponentModel.DesignImports System.Web.UI.DesignImports System.Web.UIImports System
<Designer(GetType(ExampleControlDesigner)), . . . > Public Class ExampleControl Inherits System.Web.UI.WebControls.WebControl
Dim _url As String
<Bindable(True), Category("Appearance"), DefaultValue("")> Property URL() As String Get Return _url End Get
Set(ByVal Value As String) _url = Value End Set End Property
. . .End Class
Public Class ExampleControlDesigner Inherits ControlDesigner
Protected Overrides Sub OnClick(ByVal e As DesignerRegionEventArgs) Dim iwfbuis as IWebFormsBuilderUIService Dim ctl As ExampleControl
Mybase.OnClick(e) ctl = Component iwfbuis = GetService(GetType(IWebFormsBuilderUIService)) try ctl.URL = iwfbuis.BuildUrl(Nothing, ctl.URL, RootDesigner.DocumentUrl, "Please Choose a URL", "", UrlBuilderOptions.None) catch ex as exception Msgbox(ex.Message) end try UpdateDesignTimeHtml() End Sub
The above code would bring up Visual Studio's URL dialog when the user clicked on the control, and set the control's URL property to the user's selection.
I don't have any acceptance-level tests for IWebFormsBuilderUIService.BuildUrl, because even if this method were completely busted beyond usability, it wouldn't especially hurt the other testers on our team or the other teams that depend on ASP.NET. However, I do have plenty of regular functional tests for the feature that I plan to automate, and the plan for this area looks like this:
Testcase Breakout for BuildUrl Hierarchy: All Testcases -> Web.NET -> Page & Controls -> Page Framework -> Designers -> Control Designers Extensibility -> Host Services -> IWebFormsBuilderUIService BuildUrl ClayCo Area Description Host-implemented method for bringing up its own URI-picking dialog. BuildUrl01 - Call and (from Venus) cancel the dialog Pri 2, Coding 1) Verify initialURL is returned. BuildUrl02 - Call (from ControlDesigner) and enter (from Venus) an absolute URL Pri 2, Coding Abstract:All scenarios assume UrlBuilderOptions is set to NoAbsolute unless stated otherwise. Scenarios:1) Use http://localhost/<currentapp>, verify relative conversion2) Call same with UrlBuilderOptions set to None, verify no conversion3) Use http://localhost/<currentapp>/, verify relative conversion4) Use http://localhost/<currentapp>/Page2.aspx, verify relative conversion5) Use https://localhost/AnotherApp/Page.aspx, verify relative conversion6) Use ftp://ftp.is.co.za/rfc/rfc1808.txt7) Use gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles8) Use mailto:clayco@microsoft.com9) Use news:comp.infosystems.www.servers.unix10) Use telnet://melvyl.ucop.edu/11) Use http://localhost/a/./g.aspx, verify relative conversion12) Call same with UrlBuilderOptions set to None, verify no conversion13) Use http://localhost/a/b/../g.aspx, verify relative conversion14) Call same with UrlBuilderOptions set to None, verify no conversion15) Use http://localhost/test., verify relative conversion16) Call same with UrlBuilderOptions set to None, verify no conversion17) Use http://localhost/.aspx, verify relative conversion18) Call same with UrlBuilderOptions set to None, verify no conversion19) Use http://localhost/..aspx, verify relative conversion20) Call same with UrlBuilderOptions set to None, verify no conversion21) Use 256-character URI22) Use string containing Arabic Letter Khah and U+4E2E (catch). BuildUrl03 - Call (from ControlDesigner) and enter (from Venus) a relative URL Pri 2, Coding Abstract:All scenarios assume UrlBuilderOptions is set to NoAbsolute unless stated otherwise. Scenarios:1) Use //localhost/<currentapp>/Page2.aspx, verify an app-relative URL is returned2) Call same with UrlBuilderOptions set to None, verify absolute conversion3) Use /<currentapp>/Page2.aspx, verify an app-relative URL is returned4) Call same with UrlBuilderOptions set to None, verify absolute conversion5) Use Page2.aspx6) Call same with UrlBuilderOptions set to None, verify absolute conversion7) Use //www.yahoo.com:80/, verify an absolute URL is returned8) Use /./Page2.aspx, verify an app-relative URL is returned9) Call same with UrlBuilderOptions set to None, verify absolute conversion10) Use /../Page2.aspx11) Call same with UrlBuilderOptions set to None, verify absolute conversion12) Use http.aspx13) Call same with UrlBuilderOptions set to None, verify absolute conversion14) Use test.15) Call same with UrlBuilderOptions set to None, verify absolute conversion16) Use .aspx17) Call same with UrlBuilderOptions set to None, verify absolute conversion18) Use test..19) Call same with UrlBuilderOptions set to None, verify absolute conversion20) Use ..aspx21) Call same with UrlBuilderOptions set to None, verify absolute conversion22) Use ./../test.aspx, verify an app-relative URL is returned23) Call same with UrlBuilderOptions set to None, verify absolute conversion24) Use ./SubDir/., verify an app-relative URL is returned25) Call same with UrlBuilderOptions set to None, verify absolute conversion26) Use SubDir/./Page2.aspx27) Call same with UrlBuilderOptions set to None, verify absolute conversion28) Use SubDir/../Page2.aspx29) Call same with UrlBuilderOptions set to None, verify absolute conversion30) Use Test;x=1/./Page2.aspx31) Call same with UrlBuilderOptions set to None, verify absolute conversion32) Use Test;x=1/../Page2.aspx33) Call same with UrlBuilderOptions set to None, verify absolute conversion34) Use ., verify an app-relative URL is returned35) Call same with UrlBuilderOptions set to None, verify absolute conversion36) Use ./, verify an app-relative URL is returned37) Call same with UrlBuilderOptions set to None, verify absolute conversion38) Use ..39) Call same with UrlBuilderOptions set to None, verify absolute conversion40) Use ../41) Call same with UrlBuilderOptions set to None, verify absolute conversion42) Use ../Page2.aspx43) Call same with UrlBuilderOptions set to None, verify absolute conversion44) Use ../..45) Call same with UrlBuilderOptions set to None, verify absolute conversion46) Use ../../47) Call same with UrlBuilderOptions set to None, verify absolute conversion48) Use ../../Page2.aspx49) Call same with UrlBuilderOptions set to None, verify absolute conversion50) Use 256-character URI51) Use string containing Arabic Letter Ghain and U+3A2E (lift up). BuildUrl04 - InitialUrl paramerter scenarios Pri 2, Coding 1) Use current web application folder's absolute URL, verify UI in Venus2) Use current web application folder's relative URL, verify UI in Venus3) Use current Page's URL, verify UI in Venus4) Use image file URL, verify UI in Venus5) Use absolute path to virtual sibling directory, verify UI in Venus6) Use non-existent absolute path to sibling directory, verify UI in Venus7) Use absolute path to virtual parent directory, verify UI in Venus8) Use absolute path to virtual child directory, verify UI in Venus9) Use relative path to virtual sibling directory, verify UI in Venus10) Use relative path to virtual parent directory, verify UI in Venus11) Use relative path to virtual child directory, verify UI in Venus12) Use http://, ftp://, and file:// URLs to test machine, verify UI in Venus13) Use URL to another machine, verify UI in Venus14) Use http://www.microsoft.com/, verify error BuildUrl05 - BaseUrl parameter scenarios Pri 2, Coding Abstract:All scenarios assume UrlBuilderOptions is set to NoAbsolute unless stated otherwise. Scenarios:1) Use current web application folder's absolute URL, verify relative URL calculation2) Use current web application folder's relative URL, verify relative URL calculation3) Use current Page's URL, verify relative URL calculation4) Use image file URL, verify relative URL calculation5) Use absolute path to virtual sibling directory, verify relative URL calculation6) Use absolute path to virtual parent directory, verify relative URL calculation7) Use absolute path to virtual child directory, verify relative URL calculation8) Use relative path to virtual sibling directory, verify relative URL calculation9) Use relative path to virtual parent directory, verify relative URL calculation10) Use relative path to virtual child directory, verify relative URL calculation11) Use http://, ftp://, and file:// URLs to the same machine, verify absolute URLs are used12) Use URL to another machine, verify relative and absolute paths on local and remote machines.13) Use http://www.microsoft.com/, verify absolute paths get used.14) Use String.Empty, verify absolute paths get used.15) Use current web application folder's absolute URL when options is None, verify absolute URL16) Use current web application folder's relative URL when options is None, verify absolute URL17) Use current Page's URL when options is None, verify absolute URL18) Use image file URL when options is None when options is None, verify absolute URL19) Use absolute path to virtual sibling directory when options is None, verify absolute URL20) Use absolute path to virtual parent directory when options is None, verify absolute URL21) Use absolute path to virtual child directory when options is None, verify absolute URL22) Use relative path to virtual sibling directory when options is None, verify absolute URL23) Use relative path to virtual parent directory when options is None, verify absolute URL24) Use relative path to virtual child directory when options is None, verify absolute URL BuildUrl06 - Caption parameters Pri 2, Coding Abstract:Perform standard string tests and verify in Venus Scenarios:1) S1) Verify default property value2) S2) Verify attribute value is not in HTML view3) S3) Set to all numbers4) S4) Set attribute to (nothing) in HTML view5) S5) Set to 1 character6) S6) Set attribute to space in HTML view7) S7) Set attribute without quotes in HTML view8) S8) Set property to DblQuote-space-DblQuote in Design view9) S9) Set property to Quote-space-Quote in Design view10) S10) set property to: DblQuote-Quote-&-Quote-DblQuote; verify11) S11) set attribute to: 3DblQuote-'''abc'''-3DblQuote; verify12) S12) set attribute to: DblQuote-@#$%-CrLf-GreaterThan-)(*^-DblQuote; verify13) S13) Set property to "dadadada" in prop grid14) S14) Set to long string15) S15) Set to a random intl string and verify16) S16) Set to an Intl string of problem characters17) S17) Set to a random unicode string BuildUrl07 - Filter parameter scenarios Pri 2, Coding Abstract:Use Standard String tests and verify expected value in Venus Scenarios:1) S1) Verify default property value2) S2) Verify attribute value is not in HTML view3) S3) Set to all numbers4) S4) Set attribute to (nothing) in HTML view5) S5) Set to 1 character6) S6) Set attribute to space in HTML view7) S7) Set attribute without quotes in HTML view8) S8) Set property to DblQuote-space-DblQuote in Design view9) S9) Set property to Quote-space-Quote in Design view10) S10) set property to: DblQuote-Quote-&-Quote-DblQuote; verify11) S11) set attribute to: 3DblQuote-'''abc'''-3DblQuote; verify12) S12) set attribute to: DblQuote-@#$%-CrLf-GreaterThan-)(*^-DblQuote; verify13) S13) Set property to "dadadada" in prop grid14) S14) Set to long string15) S15) Set to a random intl string and verify16) S16) Set to an Intl string of problem characters17) S17) Set to a random unicode string Testcase Summary Info: Design: Pending Scenario Review: Coding: 7 Pending Code Review: Complete: Total: 7
Testcase Summary Info:
This is typical -- every feature area has a lot more tests defined for it than get will ever be run on any given build. We rely on testers using the builds for ad-hoc testing and writing automation to find bugs, and rely on automated tests to catch regressions in later builds. We also use full test passes like this to get a deeper sense of the product's quality at a few key intervals (such as earlier this month -- we wanted to catch isses in advance of the first large-scale Beta release of the product and get a sense of how much more work is needed to stabilize the product's quality before we ship).
And we did find bugs. In the above test plan, the very first test case failed during the full test pass. If a user clicked “Cancel” in the URL dialog, an empty string was returned by the method, rather than the initialURL parameter value. This has already been fixed, by the way.