TFS API Part 54 – Add Associate Automation Programmatically

03/03/2014

tags: , , ,
no comments

Microsoft Test Manager allows you to connect Test Automation to Manual Test, this is part of end to end solution, once you connect Automated Test to Manual Test you can use it in Lab Manager.

You can link any unit test, coded UI test, or generic test to a test case. You’ll want to link a test method that performs the test described by the test case. Typically these are integration tests. The results of automated and manual tests appear together. If the test cases are linked to backlog items, stories, or other requirements, you can review the test results by requirement.

Today post we show how to add automated test association using TFS API.

SNAGHTML4e925c2SNAGHTML4e945df

Download Demo Project

I’ve created WPF Application and added the following assemblies into my project:

  • Microsoft.TeamFoundation.Client
  • Microsoft.TeamFoundation.Common
  • Microsoft.TeamFoundation.TestManagement.Client.dll
  • Microsoft.TeamFoundation.TestManagement.Common.dll
  • Microsoft.TeamFoundation.WorkItemTracking.Client.dll

Step 1: Connecting to TFS

As always we need to connect TFS before doing anything, after the connection completed I’m calling GetTestCases.

private void btnConnect_Click(object sender, RoutedEventArgs e)
{
    TeamProjectPicker tpp = new TeamProjectPicker(TeamProjectPickerMode.SingleProject, false);
    if (tpp.ShowDialog() == System.Windows.Forms.DialogResult.OK && tpp.SelectedTeamProjectCollection != null)
    {
        _tfs = tpp.SelectedTeamProjectCollection;
        _store = new WorkItemStore(_tfs);
        ITestManagementService service = (ITestManagementService)_tfs.GetService(typeof(ITestManagementService));
        _project = tpp.SelectedProjects[0];
        _testProject = (ITestManagementTeamProject)service.GetTeamProject(_project.Name);

        GetTestCases();
    }
}

GetTestCases method is very simple and this is just for demo purposes.

private void GetTestCases()
{
    testCasesList.ItemsSource = _store.Query("select * from WorkItems where [Work Item Type] = 'Test Case' AND [Team Project] = '" + _project.Name + "'");
}

Step 2: Get Test Case Automation Details

To get Test Case automation details we need to use ITmiTestImplementation interface that represents a link to an automated test in the unit test infrastructure.

private void LoadTestCaseAutomationDetails(ITestCase test)
{
    ITmiTestImplementation implementation = (ITmiTestImplementation)test.Implementation;
    if (implementation != null)
    {
        txtAutomationType.Text = implementation.TestType;
        txtAutomationId.Text = implementation.TestId.ToString();
        txtAutomationStorage.Text = implementation.Storage;
        txtAutomationName.Text = implementation.TestName;
        btnRemove.IsEnabled = true;
    }
    else
        txtAutomationType.Text =
            txtAutomationId.Text =
            txtAutomationStorage.Text =
            txtAutomationName.Text = string.Empty;
}

Step 3: Load Test Assemblies

Last start with OpenFileDialog to choose a specific TestAssembly.

private void btnAdd_Click(object sender, RoutedEventArgs e)
{
    var openFileDialog = new OpenFileDialog()
    {
        Filter = "Test Assembly (*.dll)|*.dll"
    };

    if (openFileDialog.ShowDialog() == true)
    {
        TestAssembly = openFileDialog.FileName;

        if (File.Exists(TestAssembly))
        {
            btnRemove.IsEnabled = false;
            btnSave.IsEnabled = true;
            LoadTests(TestAssembly);
        }
    }
    else
    {
        btnRemove.IsEnabled = true;
        btnSave.IsEnabled = false;
    }
}

Then using Mono.Cecil we’ll extract all test methods with “Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute” attribute.

public async void LoadTests(string assemblyLocation)
        {
            List<string> _allTestMethods = await Task.Run(() => LoadTestMethods(assemblyLocation).ToList());
            List<string> tests = new List<string>();
            foreach (var allTestMethod in _allTestMethods)
            {
                tests.Add(allTestMethod);
            }

            txtAutomationName.ItemsSource = tests;
            if (txtAutomationName.Items.Count > 0)
                txtAutomationName.SelectedItem = txtAutomationName.Items[0];
        }

        private IEnumerable<string> LoadTestMethods(string assemblyLocation)
        {
            var assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(assemblyLocation);
            var allMethods = assembly.MainModule.Types
                    .SelectMany(t => t.Methods);

            return allMethods.Where(m => m.CustomAttributes.Any(a => a.AttributeType.FullName == "Microsoft.VisualStudio.TestTools.UnitTesting.TestMethodAttribute"))
                .Select(m => m.DeclaringType.FullName + "." + m.Name)
                .OrderBy(n => n);
        }

Step 4: Associate Test Automation

Using CreateTmiTestImplementation method to create new Implementation object, passing to that mehod the Test Method Name, Test Type (You can change it from UI Test to other values) and finally the Test Assembly File name.

The rest is for creating unique test id – this value will not appear in MTM but required for associating automation.

private void AssociateAutomation(ITestCase testCase, string automationTestName, string filename)
        {
            var crypto = new SHA1CryptoServiceProvider();
            var bytes = new byte[16];
            Array.Copy(crypto.ComputeHash(Encoding.Unicode.GetBytes(automationTestName)), bytes, bytes.Length);
            var automationGuid = new Guid(bytes);

            testCase.Implementation = testCase.Project.CreateTmiTestImplementation(
                    automationTestName, "UI Test",
                    filename, automationGuid);

            testCase.Save();
        }
And don’t forget saving the test case 🙂

Step 5: Remove Associate Automation

To remove associate automation just set Test Case Implementation to null, and one other thing that you might want to do is setting AutomationStatus field to “Not Automated”.

And don’t forget saving the test case 🙂

        private void RemoveAutomation(ITestCase testCase)
        {
            testCase.Implementation = null;
            testCase.CustomFields["Microsoft.VSTS.TCM.AutomationStatus"].Value = "Not Automated";
            testCase.Save();

            LoadTestCaseAutomationDetails(testCase);
        }

Download Demo Project

Add comment
facebook linkedin twitter email

Leave a Reply