Friday, October 26, 2012

VS 2010 – Generating a TRX file for a list of Tests


I came across a situation where I needed to generate a TRX file dynamically for a set of tests. This TRX would then to be used to rerun the set of tests.

To create a utility for this, I needed 3 pre-requisites:

·         List of test names

·         A TRX file template with one test

·         VSMDI file which has the test case details

The TRX template looks like this:

<?xml version="1.0" encoding="UTF-8"?>

<TestRun id="75ef9a27-b8ce-4c81-a2bb-fb3e26088e32" name="xxx" runUser="xxx" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">

          <TestSettings name="Local" id="3402c4f6-3b10-4472-9f2c-14a883c33075">

                   <Description>These are default test settings for a local test run.</Description>

                   <Deployment enabled="false" runDeploymentRoot="anujc_ANUJDEV1 2012-10-09 17_43_06">

                   </Deployment>

                   <Execution hostProcessPlatform="MSIL">

                             <TestTypeSpecific>

                                      <UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">

                                                <AssemblyResolution applicationBaseDirectory="xxx ">

                                                          <TestDirectory useLoadContext="true" />

                                                          <RuntimeResolution>

                                                                   <Directory path=" xxx " includeSubDirectories="true" />

                                                          </RuntimeResolution>

                                                </AssemblyResolution>

                                      </UnitTestRunConfig>

                             </TestTypeSpecific>

                             <AgentRule name="LocalMachineDefaultRole">

                             </AgentRule>

                   </Execution>

          </TestSettings>

          <Times creation="2012-10-09T17:43:06.8818053-07:00" queuing="2012-10-09T17:43:08.3979569-07:00" start="2012-10-09T17:43:08.5789750-07:00" finish="2012-10-09T18:01:43.5194579-07:00" />

          <ResultSummary outcome="Failed">

                   <Counters total="1" executed="1" passed="0" error="0" failed="0" timeout="0" aborted="0" inconclusive="0" passedButRunAborted="0" notRunnable="0" notExecuted="0" disconnected="0" warning="0" completed="1" inProgress="0" pending="0" />

          </ResultSummary>

          <TestDefinitions>

                   <UnitTest name="DefaultTestName" storage=" xxx">

                             <Description>DefaultDescription</Description>

                             <Execution id="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7" />

                             <Properties>

                                      <Property>

                                                <Key>JobID</Key>

                                                <Value>133069</Value>

                                      </Property>

                             </Properties>

                             <TestMethod codeBase=" xxx" adapterTypeName="Microsoft.VisualStudio.TestTools.TestTypes.Unit.UnitTestAdapter, Microsoft.VisualStudio.QualityTools.Tips.UnitTest.Adapter, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" className=" xxx, Federation4.5, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" name="DefaultTestName" />

                   </UnitTest>

          </TestDefinitions>

          <TestLists>

                   <TestList name="All Loaded Results" id="19431567-8539-422a-85d7-44ee4e166bda" />

          </TestLists>

          <TestEntries>

                   <TestEntry testId="5099c33a-7e6b-4dff-8872-c0b6f614bbed" executionId="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7" testListId="19431567-8539-422a-85d7-44ee4e166bda" />

          </TestEntries>

          <Results>

                   <UnitTestResult executionId="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7" testId="5099c33a-7e6b-4dff-8872-c0b6f614bbed" testName="DefaultTestName" computerName=" xxx" duration="00:00:15.4887422" startTime="2012-10-09T17:43:08.7109882-07:00" endTime="2012-10-09T17:43:25.0076177-07:00" testType="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b" outcome="Completed" testListId="19431567-8539-422a-85d7-44ee4e166bda" relativeResultsDirectory="e58026f9-1eb9-4f96-8fc9-e672dce1e6c7">

                             <Output>

                                      <StdOut>Fake Log</StdOut>

                             </Output>

                   </UnitTestResult>

          </Results>

</TestRun>

Now I created one method which reads the test properties from the VSMDI

static string GetTestcaseIdFromVsmdi(string testcase)

        {

            XmlDocument doc = new XmlDocument();

            doc.Load(oldVsmdi);

            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(new NameTable());

            namespaceManager.AddNamespace("ns", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");

 

            XmlNode testLink = doc.SelectSingleNode("//ns:TestLink[@name='" + testcase + "']", namespaceManager);

            return testLink.Attributes["id"].Value;

        }

The below method creates a TRX for the list of test names

static void CreateNewTrx(List<string> selectedTests)

        {

            XmlDocument doc = new XmlDocument();

            doc.Load(oldTrx);

            XmlNamespaceManager namespaceManager = new XmlNamespaceManager(new NameTable());

            namespaceManager.AddNamespace("ns", "http://microsoft.com/schemas/VisualStudio/TeamTest/2010");

 

            XmlNode unitTest = doc.SelectSingleNode("//ns:UnitTest", namespaceManager);

            XmlNode testEntry = doc.SelectSingleNode("//ns:TestEntry", namespaceManager);

            XmlNode unitTestResult = doc.SelectSingleNode("//ns:UnitTestResult", namespaceManager);

 

            XmlNode counters = doc.SelectSingleNode("//ns:ResultSummary/ns:Counters", namespaceManager);

            counters.Attributes["total"].Value = selectedTests.Count.ToString();

            counters.Attributes["executed"].Value = selectedTests.Count.ToString();

            counters.Attributes["completed"].Value = selectedTests.Count.ToString();

 

            foreach (string selectedTest in selectedTests)

            {

                string testId = GetTestcaseIdFromVsmdi(selectedTest);

                string executionId = Guid.NewGuid().ToString();

                if (doc.SelectSingleNode("//ns:UnitTest[@name='DefaultTestName']", namespaceManager) != null)

                {

                    unitTest.Attributes["name"].Value = selectedTest;

                    unitTest.Attributes["id"].Value = testId;

                    unitTest.SelectSingleNode("ns:Execution", namespaceManager).Attributes["id"].Value = executionId;

                    unitTest.SelectSingleNode("ns:TestMethod", namespaceManager).Attributes["name"].Value = selectedTest;

                    testEntry.Attributes["testId"].Value = testId;

                    testEntry.Attributes["executionId"].Value = executionId;

                    unitTestResult.Attributes["executionId"].Value = executionId;

                    unitTestResult.Attributes["testName"].Value = selectedTest;

                    unitTestResult.Attributes["testId"].Value = testId;

                }

                else

                {

                    XmlNode newUnitTest = unitTest.Clone();

                    newUnitTest.Attributes["name"].Value = selectedTest;

                    newUnitTest.Attributes["id"].Value = testId;

                    newUnitTest.SelectSingleNode("ns:Execution", namespaceManager).Attributes["id"].Value = executionId;

                    newUnitTest.SelectSingleNode("ns:TestMethod", namespaceManager).Attributes["name"].Value = selectedTest;

                    unitTest.ParentNode.AppendChild(newUnitTest);

 

                    XmlNode newtestEntry = testEntry.Clone();

                    newtestEntry.Attributes["testId"].Value = testId;

                    newtestEntry.Attributes["executionId"].Value = executionId;

                    testEntry.ParentNode.AppendChild(newtestEntry);

 

                    XmlNode newUnitTestResult = unitTestResult.Clone();

                    newUnitTestResult.Attributes["executionId"].Value = executionId;

                    newUnitTestResult.Attributes["testName"].Value = selectedTest;

                    newUnitTestResult.Attributes["testId"].Value = testId;

                    unitTestResult.ParentNode.AppendChild(newUnitTestResult);

                }

            }

 

            doc.Save(newTrx);

        }

Now you are ready to run the tests from the TRX.

The only thing to note is that while running the tests from the Test Results window, don’t check any test. Just click Run and Enjoy!

 

Tuesday, September 11, 2012

Machine stuck in “Applying computer settings” state

I was facing a problem where one of our VMs was stuck in “Applying computer settings” state after a reboot.
I followed the below steps the fix the issue:
  • Logged in to the VM in Safe mode with Networking
  • Removed the VM from domain
  • Rebooted the VM
  • Flushed DNS cache by using ipconfig /flushdns
  • Released the IP by using ipconfig /release
  • Renewed the IP by using ipconfig /renew
  • Added the VM back to domain
  • Rebooted the VM

Thursday, August 23, 2012

SQL Server Database Project - Warning is shown as Error

While trying to build a database project, I was getting an error:
Error:  SQL01945: Warning! The maximum key length is 900 bytes. The index 'xxx' has maximum length of 1024 bytes. For some combination of large values, the insert/update operation will fail.

Although this was a warning, the project was failing to build and it was shown as a error.

The fix was to edit the project file in xml and set TreatTSqlWarningsAsErrors to False

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <OutputPath>.\sql\debug\</OutputPath>
    <BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
    <TargetDatabase>xxx</TargetDatabase>
    <TreatTSqlWarningsAsErrors>False</TreatTSqlWarningsAsErrors>
    <SuppressTSqlWarnings />
    <NoWarn>
    </NoWarn>
  </PropertyGroup>

SSDT Conversion - SQL72027: File master.dacpac does not exist.

I was converting a database project to SSDT by following the steps at http://msdn.microsoft.com/en-us/library/hh272689(v=vs.103).aspx

The conversion was successful but when I tried to build the sqlproj, it gave the following error:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets(494,5): Error:  SQL72027: File "<project directory>\master.dacpac" does not exist.

To fix this error master.dacpac needs to be copied in the project directory.
If the Target Plaform is "SQL Azure", it can be copied from
"D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\SQLDB\Extensions\SqlServer\Azure\SQLSchemas"

Otherwise based on the platform, copy from the corresponding directory from
"D:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\SQLDB\Extensions\SqlServer"

Monday, August 20, 2012

SqlPackage.exe - Automating SSDT Deployment

To know about SQL Server Data Tools (SSDT), take a look at http://msdn.microsoft.com/en-us/library/hh272686(v=vs.103).aspx

Below are the steps for automating the SSDT deployment:
  • Create a Folder on the deployment machine. We can call it C:\SSDT
  • Make sure the files from the following folders on the development machine are copied in SSDT folder on the deployment machine:
    • C:\Program Files (x86)\Microsoft SQL Server\110\DAC\bin
    • C:\Windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.TransactSql.ScriptDom\v4.0_11.0.0.0__89845dcd8080cc91
  • Copy the files from the Build Output of the SSDT Project in a Folder on the deployment machine. We can call it C:\Build
  • Make sure that you have the connection string of the Target Database where you want to depoy. We can call it connStr
  • Now you can publish or generate the scripts for the database deployment (Steps are same for Full or Incremental Deployment)
    • To Publish, run the command: C:\SSDT\SqlPackage.exe /Action:Publish /SourceFile:"C:\Build\MyDatabase.dacpac" /TargetConnectionString:"connStr"
    • To Generate Scripts, run the command: C:\SSDT\SqlPackage.exe /Action:Script /SourceFile:"C:\Build\MyDatabase.dacpac" /TargetConnectionString:"connStr" /OutPutPath:"C:\Build\MyDatabase.sql"
This is great feature for SQL Azure databases since incremental updates can be applied very easily without making the sql scripts SQL Azure compatible.