Previously I’ve covered how to programmatically create a bug in TFS. In this post, we’ll create a test case to cover it.
Set-up
What we’re going to do here is to create a new test case based on the bug that we created in the linked post, then we’re going to copy key values across, and link the two.
First, we need to do some re-factoring; the section of code the saves the work item can be extracted into something like this:
private static ActionResult CheckValidationResult(WorkItem workItem)
{
var validationResult = workItem.Validate();
ActionResult result = null;
if (validationResult.Count == 0)
{
// Save the new work item.
workItem.Save();
result = new ActionResult()
{
Success = true,
Id = workItem.Id
};
}
else
{
result = ParseValidation(validationResult);
}
return result;
}
ActionResult is here for reference:
public class ActionResult
{
public bool Success { get; set; }
public List<string> ErrorCodes { get; set; }
public int Id { get; set; }
}
Let’s re-visit what the code to create the bug looks like now:
public static ActionResult CreateNewBug(string uri, string teamProject, string title, string description,
string area, string iteration, string assignee, string reproductionSteps)
{
var project = TFSUtilLibrary.TeamProjectHelper.GetTeamProject(uri, teamProject);
return CreateNewBug(project, title, description, area, iteration, assignee, reproductionSteps);
}
private static ActionResult CreateNewBug(Project teamProject, string title, string description,
string area, string iteration, string assignee, string reproductionSteps)
{
WorkItemType workItemType = teamProject.WorkItemTypes["Bug"];
// Create the work item.
WorkItem newBug = new WorkItem(workItemType);
newBug.Title = title;
newBug.Description = description;
newBug.AreaPath = area;
newBug.IterationPath = iteration;
newBug.Fields["Assigned To"].Value = assignee;
newBug.Fields["Repro Steps"].Value = reproductionSteps;
newBug.Fields["Tags"].Value = "Tagtest1, tagtest2, tagtest3";
ActionResult result = CheckValidationResult(newBug);
return result;
}
You’ll notice that I’ve added some tags. Why will become apparent later.
Finding a Work Item
We’re creating a test case for a work item; consequently, we need to be able to retrieve a WorkItem, given an ID:
private static WorkItem GetWorkItem(string uri, int testedWorkItemId)
{
TfsTeamProjectCollection tfs;
tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(uri)); // https://mytfs.visualstudio.com/DefaultCollection
tfs.Authenticate();
var workItemStore = new WorkItemStore(tfs);
WorkItem workItem = workItemStore.GetWorkItem(testedWorkItemId);
return workItem;
}
Get a Team Project
The next step is that we’ll need to be able to find a team project (we just will):
public static Project GetTeamProject(string uri, string name)
{
TfsTeamProjectCollection tfs;
tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(uri)); // https://mytfs.visualstudio.com/DefaultCollection
tfs.Authenticate();
var workItemStore = new WorkItemStore(tfs);
var project = (from Project pr in workItemStore.Projects
where pr.Name == name
select pr).FirstOrDefault();
if (project == null)
throw new Exception($"Unable to find {name} in {uri}");
return project;
}
Create the Test Case
We now have everything that we need to create the test case. Here’s the parent code that will create the bug:
var result = WorkItemHelper.CreateNewBug(TFSUri, "TFSSandbox",
"Test new bug", "New bug description", @"TFSSandbox\\Team 12", @"TFSSandbox\\Iteration 1", "Paul Michaels",
"Click the screen");
if (result.Success)
{
// Now create the test case
var resultTestCase = WorkItemHelper.CreateNewTestCase(
TFSUri, "TFSSandbox", result.Id, "Test case description", "Paul Michaels",
"reproduction steps here");
}
So, we’re creating a bug and, if it’s successful, we’re creating a test case for it; the CreateNewTestCase code looks like this:
public static ActionResult CreateNewTestCase(string uri, string teamProject,
int testedWorkItemId, string description, string assignee, string reproductionSteps)
{
var project = GetTeamProject(uri, teamProject);
var workItem = GetWorkItem(uri, testedWorkItemId);
return CreateNewTestCase(uri, project, workItem, description, assignee, reproductionSteps);
}
private static ActionResult CreateNewTestCase(string uri, Project project, WorkItem testedWorkItem, string description, string assignee, string reproductionSteps)
{
WorkItemType workItemType = project.WorkItemTypes["Test Case"];
// Create the work item.
WorkItem newTestCase = new WorkItem(workItemType);
newTestCase.Title = $"Test {testedWorkItem.Title}";
newTestCase.Description = description;
newTestCase.AreaPath = testedWorkItem.AreaPath;
newTestCase.IterationPath = testedWorkItem.IterationPath;
newTestCase.Fields["Assigned To"].Value = assignee;
// Copy tags
newTestCase.Fields["Tags"].Value = testedWorkItem.Fields["Tags"].Value;
ActionResult result = CheckValidationResult(newTestCase);
if (result.Success)
{
CreateTestedByLink(uri, testedWorkItem, result.Id);
}
return result;
}
Couple of things to note here; the first is the tags - we’re copying them from the bug (see references). The second is that we are linking the two.
Links
Here’s how I created the link:
private static void CreateTestedByLink(string uri, WorkItem testedWorkItem, int newTestCaseId)
{
TfsTeamProjectCollection tfs;
tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(uri)); // https://mytfs.visualstudio.com/DefaultCollection
tfs.Authenticate();
var workItemStore = new WorkItemStore(tfs);
var linkTypes = workItemStore.WorkItemLinkTypes;
WorkItemLinkType testedBy = linkTypes.FirstOrDefault(lt => lt.ForwardEnd.Name == "Tested By");
WorkItemLinkTypeEnd linkTypeEnd = testedBy.ForwardEnd;
//Add the link as related link.
testedWorkItem.Links.Add(new RelatedLink(linkTypeEnd, newTestCaseId));
var result = CheckValidationResult(testedWorkItem);
}
It feels like there might be a slicker way than referencing “Tested By” by name, but this is the only way I could find.
Here’s the created bug with a linked test case:
Conclusion
As with the previous post, I’m not trying to re-write TeamCity or anything here; this was just born out of some pain with manually setting these things up.
You’ll also notice that I’ve left the Test Steps; I’ll come back to them shortly (and by ‘shortly’, I mean in a later post).
References