September 2007 - Posts - From the software development trenches

September 2007 - Posts

Izindaba #11
28 September 07 08:02 AM | cjlotz | with no comments

It is time for another weekly roundup of news that focuses on .NET, agile and general development related content:

  1. Armchair Agilist - Scott Bellware expresses his frustration with folks from within the .NET Community who keep on criticizing agile development without having done any actual agile development themselves.
  2. Why Fixed Price, Scope Bids Are Incompatible With Software Development - A thought provoking post by Mats Helander.
  3. Continuous Testing Explained - The future of TDD?
  4. Everything Is Fast For Small n - Jeff Atwood exhorts people to test their applications with a reasonably large volume of data.
  5. Spell Checker Added to VS 2008 - News from InfoQ on the re-inclusion of the spell checking rules of FxCop to VS 2008.
  6. Code Analysis support for anonymous methods and lambda expressions in VS 2008 - News from the Code Analysis Team.
  7. VS 2008 Performance Improvements - Somasegar runs through a list of the major performance improvements made in VS 2008.
  8. URI Format - Part 1: Addressing resources using URI path segments - The Astoria Team highlights their thinking surrounding the appropriate URI format for Astoria and asks for further community input.
  9. Astoria data sources and system layering - The Astoria Team again on the support for querying any data source that has a IQueryable<T> implementation.
  10. AJAX Control Toolkit Update - News from David Anson on the recent update released.
  11. xUnit.net - Next Generation of Unit Testing Frameworks? - News from InfoQ on the new test framework announced by Jim Newkirk and Brad Wilson that aims to correct all of NUnit's mistakes and provide better support for extensibility and testing best practices. 
  12. Castle Project 1.0 RC3 - News from InfoQ on the latest release from the folks at the Castle Project.
  13. XMLPad 3 - For those of use who can't afford Altova's XML tools, here is a better, free, alternative XML editor to use than XMLNotepad.

Happy reading smile_regular

Izindaba #10
20 September 07 03:28 PM | cjlotz | with no comments

A bit earlier than normal, but it is time for another weekly roundup of news that focuses on .NET, agile and general development related content:

  1. NCover 2.0.1 released - NCover follows the route of other tools before it like TestDriven.NET, NDepend and CodeSmith and becomes a commercial product.  Here's the what's new for the latest release.
  2. NCoverExplorer 1.4.0 - Grant Drake has released an update to his excellent NCoverExplorer tool containing some fixes and new features.  This will be the last free update.
  3. CodeGear Ruby/Rails IDE - CodeGear has released their Ruby/Rails IDE that includes support for intelligent completion of dynamic methods.
  4. Astoria CTP Refresh for Visual Studio 2008 Beta 2 - Update to the May 2007 CTP to provide compatibility with the latest Entity Framework Beta 2 release.
  5. Pinpoint a performance issue using hotpath in VS 2008 - News from Profiler Team on the new HotPath feature that gives you a single click navigation to the bottleneck in your performance report.
  6. To NGen or Not to NGen - Some guidance from the CLR Code Generation Team.
  7. Parallel LINQ - The latest MSDN Magazine has a nice article that shows how PLINQ uses parallel processing to process your LINQ queries.
  8. Using C# ?? operator with LINQ - Scott Guthrie shows how to use the null coalescing operator to provide default values for nullable values in a LINQ query.
  9. .NET Type Internals - Article on CodeProject that dives deep into the CLR to understand the internals of .NET types.
  10. ASP.NET Ajax Web Service - Kazi Manzur Rashid shares some common issues with ASP.NET Ajax Web Services.
  11. Testers are pigs - Jeremy Miller warns to not forget to involve your testers from the start.
  12. Self-organisation is not boundaryless - Some agile advice from Kelly Waters.

Happy reading smile_regular

Part 7: Continuous Integration - The QtpBuild
17 September 07 09:33 PM | cjlotz | 8 comment(s)

This is the seventh post in a series where I document how to setup a Continuous Integration (CI) process using open source tools like CruiseControl.NET, NCover, NUnit, Subversion and Sandcastle together with MSBuild and VS 2005. Part 7 covers the QtpBuild and the targets and tasks used by the QtpBuild. The QtpBuild shows how to run the regression test pack using Mercury's QuickTest Professional and Mercury Quality Center

Post Updates

  • 11/12/2007: Updated the CC.Net configuration to use build queues and entity references. 
  • 28/09/2007: Changed the QtpBuild to make use of incremental builds to install/uninstall the application and to run the test cases, identified in a file, from within Mercury Quality Center.

MSBuild Scripts

As mentioned in Part 1, QTP runs on a dedicated QtpServer machine as the regression test pack takes quite some time to run through (3 hours in our scenario).  This begs the question how to invoke Qtp remotely from the BuildServer. I considered the following options:

  1. Remotely invoke Qtp using psexec from our BuildServer.
  2. Remotely invoke Qtp using DCOM from our BuildServer.  This seems possible using QTP's automation object model.
  3. Instead of remotely invoking QTP, install CC.NET on the QtpServer machine itself and create a project that monitors and triggers a build once the DeploymentBuild has been completed on the BuildServer.

Depending on your environment scenario you may choose either option 1 or 2 as it requires less configuration, but in the end I chose to not use a remove invocation mechanism in favour of option 3.  The down side is that I have to install CC.NET on the QtpServer as well.  In addition to deploying the build onto our file server, the DeploymentBuild also copies the msi onto a share for the QtpBuild to use.

Uninstall

Before running the tests the old version of our application needs to be uninstalled.

1 <Target Name="Uninstall" 2 Inputs="@(RunQtpInstallInput)" 3 Outputs="@(RunQtpInstallOutput)"> 4 5 <!-- Launch the Uninstall in silent mode --> 6 <Exec Command="msiexec /x $(DOUBLE_QUOTES)$(QtpUninstallFolder)\$(MsiInstallFile)$(DOUBLE_QUOTES) /passive /l* $(DOUBLE_QUOTES)$(QtpUninstallFolder)\Uninstall.log$(DOUBLE_QUOTES)" 7 ContinueOnError="true" /> 8 9 </Target>

Observations:

  • Lines 2-3: We use MSBuild's incremental builds feature to ensure that we do not uninstall the application if the latest version of the application is already installed on the machine.  This is accomplished by comparing the timestamp of the QtpLastInstallSucceededFile to the timestamp of the latest msi package.  If the msi package timestamp is later we know that we have a new version to install and thus need to do the uninstall.
  • Line 4: The old version of our application is uninstalled by launching Windows Installer with the /x and /passive parameters.  The /passive parameter ensures that no user interaction is required.  We also log the uninstall output to a uninstall.log file. ContinueOnError is set to true for those scenarios where the machine hasn't got an installed version of our application.

Install

Before running the tests the new version of our application needs to be installed.  As mentioned earlier, the msi is copied into the QtpInstallFolder share by the Deploy target that runs as part of the DeploymentBuild.

1 <Target Name="Install" 2 Inputs="@(RunQtpInstallInput)" 3 Outputs="@(RunQtpInstallOutput)"> 4 5 <Error Text="No QtpDeployFolder has been specified" Condition="'$(QtpDeployFolder)' == ''" /> 6 7 <!-- Copy the latest install from the build server --> 8 <Copy SourceFiles="$(QtpDeployFolder)\$(MsiInstallFile)" 9 DestinationFolder="$(QtpInstallFolder)"/> 10 11 <!-- Launch the install in silent mode --> 12 <Exec Command="msiexec /i $(DOUBLE_QUOTES)$(QtpInstallFolder)\$(MsiInstallFile)$(DOUBLE_QUOTES) /passive /l* $(DOUBLE_QUOTES)$(QtpInstallFolder)\Install.log$(DOUBLE_QUOTES) CLEAN_DATABASE=1"/> 13 14 <!-- Copy the msi to the Uninstall folder to use for later uninstallation --> 15 <Copy SourceFiles="$(QtpInstallFolder)\$(MsiInstallFile)" 16 DestinationFolder="$(QtpUninstallFolder)"/> 17 18 <Touch Files="@(RunQtpInstallOutput)" AlwaysCreate="true" /> 19 20 </Target>

Observations:

  • Lines 2-3: We use MSBuild's incremental builds feature to ensure that we do not uninstall the application if the latest version of the application is already installed on the machine.  This is accomplished by comparing the timestamp of the QtpLastInstallSucceededFile to the timestamp of the latest msi package.  If the msi package timestamp is later we know that we have a new version to install and thus need to do the install.
  • Lines 8-9: The latest msi package is copied from the server to the local machine to use for installation.
  • Line 12: The new version of our application is installed by launching Windows Installer with the /i and /passive parameters.  The /passive parameter ensures that no user interaction is required.  We also log the install output to an install.log file.  Also notice the CLEAN_DATABASE=1 statement that we pass onto the installer.  As the installer is launched in passive mode, we need to set any installer options that would normally be selected by the user via the GUI now via the command line.
  • Line 15-16: After installing the application, a copy of the msi is put into the QtpUninstallFolder to use for the next Uninstall.
  • Line 18: We touch the timestamp of the QtpLastInstallSucceededFile to support future incremental builds.

Qtp Automation

Fortunately, the help file of Mercury's QTP product has some good examples of how to automate QTP using COM automation.  I used extracts from their VBScript examples as a base for creating a RunQTP.vbs file that we use for doing our QTP automation.  As QTP stores the result for every test in XML format, the idea is to create a single XML file that contains the combined results from all the individual tests and to merge this file into the CC.NET build report.

1 Dim arTestCases, qcServer, qcUser, qcPassword 2 Dim testCasesFile, resultsDir, resultsSummaryFile 3 Dim fso, folder, subFolders, testResults, testCases 4 Dim qtApp, qtTest, qtResults 5 Dim testsPassed 6 7 testCasesFile = WScript.Arguments(0) 8 resultsDir = WScript.Arguments(1) & "\" 9 resultsSummaryFile = WScript.Arguments(2) 10 qcServer = WScript.Arguments(3) 11 qcUser = WScript.Arguments(4) 12 qcPassword = WScript.Arguments(5) 13 14 Set fso = CreateObject("Scripting.FileSystemObject") 15 Set testCases = fso.OpenTextFile(testCasesFile) 16 Set testResults = fso.CreateTextFile(resultsSummaryFile, True) 17 18 ' Build an array of test cases to use 19 arTestCases = Split(testCases.ReadAll, vbCrLf) 20 21 testCases.Close 22 Set testCases = Nothing 23 24 ' Launch QuickTest 25 Set qtApp = CreateObject("QuickTest.Application") 26 qtApp.Launch 27 qtApp.Visible = False 28 qtApp.Options.Run.RunMode = "Fast" 29 qtApp.Options.Run.ViewResults = False 30 31 Set qtResults = CreateObject("QuickTest.RunResultsOptions") 32 33 ' Connect to Quality Center 34 qtApp.TDConnection.Connect qcServer, "CCNET.DEMO", "CCNet.Demo", qcUser, qcPassword, False 35 If Not qtApp.TDConnection.IsConnected Then 36 WScript.Echo "Could not connect to Quality Center!" 37 WScript.Quit 1 38 End If 39 40 testsPassed = True 41 testResults.WriteLine("<QtpResults>") 42 43 ' Iterate through all the test cases 44 testsPassed = RunTests(arTestCases, resultsDir, testResults) 45 46 ' Close the output file 47 testResults.WriteLine("</QtpResults>") 48 testResults.Close 49 50 Set fso = Nothing 51 Set testResults = Nothing 52 53 If Not qtApp Is Nothing Then 54 ' Disconnect from Quality Center 55 qtApp.TDConnection.Disconnect 56 57 ' Close QuickTest Professional. 58 qtApp.Quit 59 End If 60 61 ' Release the created objects. 62 Set qtResults = Nothing 63 Set qtTest = Nothing 64 Set qtApp = Nothing 65 66 If (Err.Number > 0) Then 67 WScript.Echo "Run-time error occured!! " & Err.Description 68 WScript.Quit 1 69 ElseIf Not testsPassed Then 70 WScript.Echo "Tests Failed!!" 71 WScript.Quit 1 72 End If 73 74 Function RunTests(ByVal arTestCases, ByVal resultsDir, ByVal testResults) 75 76 Dim success, index 77 78 On Error Resume Next 79 success = True 80 81 ' Loop through all the tests in the arTestCases. 82 For index = 0 To UBound (arTestCases) - 1 83 If Len(arTestCases(index)) > 0 Then 84 ' Display Status 85 WScript.Echo "Running Test Case: " & arTestCases(index) 86 87 ' Open the test in read-only mode 88 qtApp.Open arTestCases(index), True 89 90 ' Get the test object and set the results location 91 Set qtTest = qtApp.Test 92 qtTest.Settings.Resources.ObjectRepositoryPath = "[QualityCenter] Subject\CCNet.Demo\Object Repository\CCNet.Demo_Obj_Rep.tsr" 93 qtTest.Settings.Resources.Libraries.RemoveAll 94 qtTest.Settings.Resources.Libraries.Add("[QualityCenter] Subject\CCNet.Demo\Functions\CCNet.Demo_Functions.txt") 95 96 ' This statement specifies a test results location. 97 qtResults.ResultsLocation = resultsDir & qtTest.Name 98 99 ' Execute the test. Instruct QuickTest Professional to wait for the test to finish executing. 100 qtTest.Run qtResults 101 102 ' Display Status 103 WScript.Echo vbTab & "Test Case finished: " & qtTest.LastRunResults.Status 104 105 success = success And (qtTest.LastRunResults.Status = "Passed" Or qtTest.LastRunResults.Status = "Warning") 106 107 ' Close the test. 108 qtTest.Close 109 110 ' Strip the unrequired results and append the test results to the overal result file 111 FormatTestResults fso, testResults, qtResults.ResultsLocation 112 End If 113 Next 114 115 RunTests = success 116 117 End Function 118 119 Sub FormatTestResults(ByVal fso, ByVal outputResults, ByVal testCaseDir) 120 121 Dim found, line, fileStream 122 123 Set fileStream = fso.OpenTextFile(testCaseDir & "\Report\Results.xml") 124 125 Do 126 line = fileStream.ReadLine 127 found = (InStr(1, line, "<Report", vbTextCompare) <> 0) 128 Loop While (found = False) 129 130 outputResults.WriteLine line 131 Do 132 outputResults.WriteLine(fileStream.ReadLine) 133 Loop While (fileStream.AtEndOfStream = False) 134 135 fileStream.Close 136 Set fileStream = Nothing 137 138 End Sub

Observations:

  • Lines 7-12:  The script file receives the files and Quality Center (QC) credentials to operate on as command line arguments.  The arguments include a file that contains the list of test cases to run; the directory to store the test results in; the results summary file that will be used to aggregate all the individual test results and lastly the QC server and QC user logon credentials.
  • Lines 14-22: We use the Scripting.FileSystemObject to build an array that contains the names of all the test cases to run.   As all the test cases are stored on our QC Server, we create a file that contains the server path of all the QC test cases to run, i.e. [QualityCenter] Subject\CCNet.Demo\Executable Scripts\Create Intermediaries.  We store a single test case per line and we parse the file to create an array of test cases to run.
  • Lines 25-38: We use the COM Automation model of QTP to start QTP and connect to the QC server.  If we are unable to connect to the QC server, we exit the script with a non-zero exit code.
  • Lines 41+48: The individual test results are added to a <QtpResults> tag within the QTP results summary file.
  • Lines 44, 74-113: We iterate through the test cases contained within the array and run these using the QTP automation objects.  For every QTP test, we open the test case, set the test result location and run the test to finally append the test result (stored in a Report\result.xml file) to the overall result summary file.
  • Lines 111, 119-138: The xml file produced by QTP contains a lot of unrequired DTD information that we do not want to include in the test result summary file.  We use the FormatTestResults procedure to strip this information from the file before appending the remainder of the test results to the overall test result summary file.
  • Lines 66-68: If a Windows Script Error occurred, we indicate this to the calling process by exiting the script with a non-zero exit code.
  • Lines 69-72: If one of the tests failed, we indicate this to the calling process by exiting the script with a non-zero exit code.

Qtp

As the RunQTP.vbs script file takes care of all of the QTP automation, all that we need to do is to invoke the script file using Windows Script Host.

1 <Target Name="Qtp" 2 Condition=" '$(CCNetProject)' != '' "> 3 4 <Error Text="No QCUser has been specified" Condition="'$(QCUser)' == ''" /> 5 <Error Text="No QCPassword has been specified" Condition="'$(QCPassword)' == ''" /> 6 7 <Message Text="$(NEW_LINE)Running QTP Regression Tests" Importance="high"/> 8 9 <CreateItem Include="$(QtpResultsFolder)\$(CCNetProject)"> 10 <Output TaskParameter="Include" ItemName="QtpOutputFolder"/> 11 </CreateItem> 12 13 <!-- Clear existing test results --> 14 <RemoveDir Directories="$(QtpOutputFolder)"/> 15 <MakeDir Directories="$(QtpOutputFolder)"/> 16 17 <!-- Run the QTP tests --> 18 <Exec Command="cscript.exe /nologo $(DOUBLE_QUOTES)$(QtpTestCasesFolder)\$(CCNetProject).TestCases.txt$(DOUBLE_QUOTES) $(DOUBLE_QUOTES)$(QtpOutputFolder)$(DOUBLE_QUOTES) $(DOUBLE_QUOTES)$(QtpOutputFolder)\$(QtpResultsSummaryFile)$(DOUBLE_QUOTES) $(DOUBLE_QUOTES)$(QCServer)$(DOUBLE_QUOTES) $(QCUser) $(QCPassword)" 19 ContinueOnError="true"> 20 <Output TaskParameter="ExitCode" ItemName="QtpExitCode"/> 21 </Exec> 22 23 <!-- Copy the QTP test results for the CCNet build before we possibly fail the build because of Qtp test failures --> 24 <CallTarget Targets="CopyQtpResults" /> 25 26 <!-- Fail the build if any test failed --> 27 <Error Text="Qtp test error(s) occured" Condition=" '%(QtpExitCode.Identity)' != '0'"/> 28 29 </Target>

Observations:

  • Lines 9-11: We create a unique test results output directory based on the name of the test suite that is being run.
  • Lines 13-15: We clear the old test results by deleting the test results output folder.
  • Line 18-21: Windows Script host is invoked to execute the RunQTP.vbs script file.  The test cases file, test result folder and test results summary file as well as Quality Center credentials are passed as command line parameters.  ContinueOnError is set to true and the result of the test run is stored in a QtpExitCode property.
  • Line 24: The CopyQtpResults target (see below) is invoked manually to copy the test results for inclusion in the CC.NET build report.
  • Line 27: We fail the build if any of the tests failed.

CopyQtpResults

1 <Target Name="CopyQtpResults" 2 Condition=" '$(CCNetProject)' != '' "> 3 4 <CreateItem Include="$(CCNetArtifactDirectory)\$(QtpResultsSummaryFile)"> 5 <Output TaskParameter="Include" ItemName="ExistingQtpResults"/> 6 </CreateItem> 7 8 <Delete Files="@(ExistingQtpResults)"/> 9 <Copy SourceFiles="$(QtpOutputFolder)\$(QtpResultsSummaryFile)" 10 DestinationFolder="$(CCNetArtifactDirectory)" 11 ContinueOnError="true"/> 12 13 </Target>

Observations:

  • Line 2: We test on the CCNetProject property to determine if the build was invoked via CC.NET.  The CCNetProject property is one of the properties created and passed on by CC.NET when using the MSBuild CC.NET task. 
  • Lines 4-8: The existing Qtp results summary file is deleted.
  • Line 9: The new Qtp results summary file is copied to the CCNetArtifactDirectory.

CruiseControl.NET Configuration

One dilemma you will face with the CC.NET configuration is that the current deployment of CC.NET does not include any style sheets for formatting the QTP results to display as part of the Web dashboard reports.  QTP itself uses different style sheets to format its own xml test results, so one option is to tweak their style sheets to conform to the CC.NET style sheet requirements.  Another option is to use the style sheets included by Owen Rogers in a post on the CC.NET Google user group - search for a post with the title "QuickTest Pro Integration".   Regardless of what style sheets you choose, remember to include these style sheets into the dashboard.config to display it on the webdashboard and also in either the ccservice.exe.config/ccnet.exe.config for publishing via the EmailPublisher.

The QtpServer uses the following CC.NET configuration.  The config is really self explanatory if you are familiar with the different CruiseControl.NET configuration options. 

1 <!DOCTYPE cruisecontrol [ 2 <!ENTITY pub "<statistics> 3 <statisticList> 4 <statistic name='Qtp Success' xpath='sum(//QtpResults/Report/Doc/Summary/@passed)' /> 5 <statistic name='Qtp Warnings' xpath='sum(//QtpResults/Report/Doc/Summary/@warnings)' /> 6 <statistic name='Qtp Errors' xpath='sum(//QtpResults/Report/Doc/Summary/@failed)' /> 7 </statisticList> 8 </statistics> 9 10 <xmllogger /> 11 12 <email from='qtpserver@yourdomain.co.za' mailhost='smtp.yourdomain.co.za' includeDetails='true'> 13 <users> 14 <user name='BuildGuru' group='buildmaster' address='developer1@yourdomain.co.za'/> 15 <user name='Developer2' group='developers' address='developer2@yourdomain.co.za'/> 16 <user name='QtpTester' group='qtptesters' address='qtptester1@yourdomain.co.za'/> 17 </users> 18 <groups> 19 <group name='developers' notification='change'/> 20 <group name='buildmaster' notification='always'/> 21 <group name='qtptesters' notification='always'/> 22 </groups> 23 </email>"> 24 25 <!ENTITY links "<externalLinks> 26 <externalLink name='Wiki' url='http://wikiserver.yourdomain.co.za/wiki' /> 27 </externalLinks>"> 28 29 <!ENTITY build "<tasks> 30 <msbuild> 31 <executable>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\MSBuild.exe</executable> 32 <workingDirectory>C:\Projects\CCNet.Demo</workingDirectory> 33 <projectFile>CCNet.Demo.proj</projectFile> 34 <buildArgs>/noconsolelogger /v:normal /p:QCUser=fred;QCPassword=password</buildArgs> 35 <targets>Uninstall,Install,Qtp</targets> 36 <timeout>14400</timeout> <!-- 4 hours --> 37 <logger>C:\Program Files\CruiseControl.NET\server\ThoughtWorks.CruiseControl.MSBuild.dll</logger> 38 </msbuild> 39 </tasks>"> 40 41 <!ENTITY header "<webURL>http://qtpserver.yourdomain.co.za/ccnet</webURL> 42 <category>RegressionTesting</category> 43 <workingDirectory>_dir</workingDirectory>"> 44 45 ]> 46 <cruisecontrol> 47 48 <project name="TestSuite1" queue="Qtp.CCNet.Demo" queuePriority="1"> 49 &header; 50 <artifactDirectory>_dir\Builds\TestSuite1\Artifacts</artifactDirectory> 51 52 <triggers> 53 <projectTrigger serverUri="tcp://buildserver.yourdomain.co.za:21234/CruiseManager.rem" project="DeploymentBuild"> 54 <triggerStatus>Success</triggerStatus> 55 <innerTrigger type="intervalTrigger" seconds="30" buildCondition="ForceBuild"/> 56 </projectTrigger> 57 </triggers> 58 59 <state type="state" /> 60 61 <labeller type="defaultlabeller"/> 62 63 &build; 64 65 <publishers> 66 <merge> 67 <files> 68 <file>_dir\Builds\TestSuite1\Artifacts\QtpResultsSummary.xml</file> 69 </files> 70 </merge> 71 72 &pub; 73 </publishers> 74 75 &links; 76 </project> 77 78 <project name="TestSuite2" queue="Qtp.CCNet.Demo" queuePriority="2"> 79 &header; 80 <artifactDirectory>_dir\Builds\TestSuite2\Artifacts</artifactDirectory> 81 82 <triggers> 83 <projectTrigger serverUri="tcp://qtpserver.yourdomain.co.za:21234/CruiseManager.rem" project="TestSuite1"> 84 <triggerStatus>Success</triggerStatus> 85 <innerTrigger type="intervalTrigger" seconds="30" buildCondition="ForceBuild"/> 86 </projectTrigger> 87 </triggers> 88 89 <state type="state" /> 90 91 <labeller type="defaultlabeller"/> 92 93 &build; 94 95 <publishers> 96 <merge> 97 <files> 98 <file>_dir\Builds\TestSuite2\Artifacts\QtpResultsSummary.xml</file> 99 </files> 100 </merge> 101 102 &pub; 103 </publishers> 104 105 &links; 106 </project> 107 108 </cruisecontrol>

Observations:

  • Lines 4-6: We use the Statistics provider to include some additional statistics for every build that includes the number of QTP tests that failed, number of tests that passed and the number of tests that raised warnings.
  • Line 35: The build uninstalls and installs the new version of the application that has been copied onto a share on the local machine before running Qtp.
  • Line 52-57: We setup TestSuite1 to fire once a successful DeploymentBuild has been completed.
  • Line 82-87: We setup TestSuite2 to fire once a successful TestSuite1 has completed.
  • Line 69+98: The combined test results summary file is merged into the CC.NET build report.

Using the above mentioned configuration it is quite possible to setup additional QTP builds on the same and different machines to create a grid of machines to run through all of your test cases more quickly.  Every build will run through a different set of test cases as identified by different Qtp test case files.  In our setup at work we have 3 machines running through all our test cases concurrently.  I leave that as a simple exercise for the reader to complete.

Next Steps

This is probably the most complex part of the whole CI process, but thankfully the COM automation interface provided by QTP makes it not too difficult to automate the whole regression test run.  The next and final post will highlight some community extensions that you can use to add some further panache to your CI Build to make it even more useful. smile_regular

 

 

 

 

 

 

 

Izindaba #9
14 September 07 08:25 AM | cjlotz | with no comments

Time for another weekly roundup of news that focuses on .NET, agile and general development related content:

  1. Visual Studio to Finally Address Performance Issues - InfoQ links to a  Channel 9 Video on the performance improvements made to the VS 2008 IDE.
  2. LINQ to SQL: Part 9 - Using a Custom LINQ Expression with the control - Scott Guthrie continues with his LINQ to SQL series.
  3. Programming Silverlight 1.0 with C#: Part 1 - Nikhil Kothari shows how to use Script# instead of Javascript to build an application that runs against Silverlight 1.0.
  4. Implementing Dynamic Searching using LINQ - The VB team shows how to construct a dynamic query at run-time using LINQ.
  5. BizTalk Integration Server now .NET 3.0 enabled - News on the release of the 2006 R2 BizTalk server that includes adapters and wizards to talk with WCF services.
  6. LINQ comes to Ruby? - Steve Eichert writes about a Ruby project Ambition that attempts to support LINQ on Ruby.
  7. Process Explorer 11 Released - A new version of this indispensable tool from the SysInternals folks now at Microsoft.
  8. Windows Live Writer Beta 3 -  A new version the blog writer I prefer.   New features include Printing and Insert Video support.
  9. .NET Ruby Connector - Free drag-and-drop control connector that allows you to use Ruby 1.8.x together with Visual Studio.
  10. TDD - It's Not About Testing .. Except When It Is - Scott Bellware on the testing/designing mindsets when doing TDD.
  11. Dependency injection Tools still have some good years left - Jeremy Miller argues the benefits of DI and the use of DI tools.
  12. The Discipline of Agile - Scott Ambler highlights the discipline required to succeed at doing agile development.

Happy reading smile_regular

Izindaba #8
07 September 07 07:47 AM | cjlotz | with no comments

Time for another weekly roundup of news that focuses on .NET and general development related content:

  1. Windows Vista Service Pack 1 Beta White Paper
  2. Counting Wastes Time and How Are You Going To USE That Information - Some thoughts from Fred George on collecting metrics and using metrics in an Agile development environment.  Scott Bellware expands on his thoughts with reference to BDD.
  3. 20 Tips to Improve ASP.NET Application Performance - Nice list of ASP.NET performance enhancement tips.
  4. MbUnit 2.4.1 Released - Andrew Stopford on the latest changes in the new release.
  5. Entity Framework for DBA's - The ADO.NET Team positions the up and coming Entity Framework for DBA's.
  6. Silverlight 1.0 Released and Silverlight for Linux - Scott Guthrie has the scoop on the latest Silverlight developments.
  7. Microsoft/Novell Collaboration on Silverlight - Miguel de Icaza on the historic Novell/Microsoft collaboration to bring Silverlight for Linux about.
  8. Behave# and NBehave merges - News on the merger of two BDD frameworks.
  9. Google Reader Adds Search - Google finally bakes search into Google Reader itself.  No more Greasemonkey scripts required! A bit strange that it took the world's leading search provider such a long time to do, but hey, I'm not complaining!
  10. BDD, TDD and the other Double D's - Jeremy Miller shared some thoughts on how many of these Double D's you need.
  11. Partial Methods: Do They Belong in C# - Some thoughts on one of the more controversial additions to C# from InfoQ.

Happy reading smile_regular