Sometimes unit testing existing code can be really hard. Especially when coding by exceptions (using Try.. Catch.. then do nothing!).
This will look a bit like this
From the outside we might not be able to test whether ReallyDoSomething has thrown an exception except if we can validate state changes done by ReallyDoSomething. And if we can't change the code much (like adding dependencies using parameters or change the return type of the method) we won't be able to write that test at all.
Another way is to use the logger to validate that.
The piece of code above use Log4Net as the logging framework and allow us to use it in our unit tests like this
Just like that we can intercept all the logged messages by our production code.
I've used this trick a few times now when other options were not available. Hope it helps.
Friday, August 31, 2012
Wednesday, August 15, 2012
TFS Queries : Searching in all work items
For an intro on LinqPad and the TFS API please read this post
For the list of all the posts in this series please read this one
To search for work items effectively we can use a special TFS API on the WorkItemStore class. The query format is based the Work Item Query Language (or WIQL ) and we can't use Linq directly, but still, we can use LinqPad to write a quick little query.
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.VersionControl.Client
Microsoft.TeamFoundation.WorkItemTracking.Client
Here we get the list of all the work items from all projects containing the word 'phone' in their title.
To find more about WIQL please take a look at the MSDN section on it.
For the list of all the posts in this series please read this one
Context
To search for work items effectively we can use a special TFS API on the WorkItemStore class. The query format is based the Work Item Query Language (or WIQL ) and we can't use Linq directly, but still, we can use LinqPad to write a quick little query.
Required references
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.VersionControl.Client
Microsoft.TeamFoundation.WorkItemTracking.Client
Query (C# Statements)
var tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection(new Uri("http://localhost:8088/tfs"));
tfs.EnsureAuthenticated();
var workItemStore = tfs.GetService<WorkItemStore>();
var title = "phone";
var query = string.Format(@"
Select [Id], [Work Item Type], [Title], [State]
Where [Title] Contains '{0}'
From WorkItems",
title);
workItemStore.Query(query).Cast<WorkItem>()
.Select(wi => new
{
wi.Id,
wi.AreaPath,
Type = wi.Type.Name,
wi.Title,
wi.State
})
.OrderBy(wi => wi.AreaPath).ThenBy(wi => wi.Type).ThenBy(wi => wi.Title)
.Dump();
Result
Here we get the list of all the work items from all projects containing the word 'phone' in their title.
To find more about WIQL please take a look at the MSDN section on it.
IOrderedEnumerable<> (1 item) | ||||
| Id | AreaPath | Type | Title | State |
|---|---|---|---|---|
| 2 | Project1 | Bug | Fix the phone number on the Contact page | Done |
Wednesday, August 1, 2012
TFS Queries: Listing all the branches
For an intro on LinqPad and the TFS API please read this post
For the list of all the posts in this series please read this one
When it comes to branches, using the TFS Web Access or Team Explorer we can navigate around the source code explorer to see branches from various Team Project and related information. But to get the big picture there is an easier way using the TFS API.
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.VersionControl.Client
Here we can see a bit more information on the branches like related parent and child branches in a simple list.
For the list of all the posts in this series please read this one
Context
When it comes to branches, using the TFS Web Access or Team Explorer we can navigate around the source code explorer to see branches from various Team Project and related information. But to get the big picture there is an easier way using the TFS API.
Required references
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.VersionControl.Client
Query (C# Statements)
var tfs = TfsTeamProjectCollectionFactory.
GetTeamProjectCollection(new Uri("http://localhost:8088/tfs"));
tfs.EnsureAuthenticated();
var versionControl = tfs.GetService<VersionControlServer>();
versionControl.QueryRootBranchObjects(RecursionType.Full)
.Where(b => !b.Properties.RootItem.IsDeleted)
.Select(s => new
{
Project = s.Properties.RootItem.Item
.Substring(0, s.Properties.RootItem.Item.IndexOf('/', 2)),
Properties = s.Properties,
DateCreated = s.DateCreated,
ChildBranches = s.ChildBranches
})
.Select(s => new
{
s.Project,
Branch = s.Properties.RootItem.Item.Replace(s.Project, ""),
Parent = s.Properties.ParentBranch != null ?
s.Properties.ParentBranch.Item.Replace(s.Project, "") : "",
Version = (s.Properties.RootItem.Version as ChangesetVersionSpec)
.ChangesetId,
DateCreated = s.DateCreated,
Owner = s.Properties.Owner,
ChildBranches = s.ChildBranches
.Where (cb => !cb.IsDeleted)
.Select(cb => new
{
Branch = cb.Item.Replace(s.Project, ""),
Version = (cb.Version as ChangesetVersionSpec).ChangesetId
})
})
.OrderBy(s => s.Project).ThenByDescending(s => s.Version)
.Dump();
Result
Here we can see a bit more information on the branches like related parent and child branches in a simple list.
IOrderedEnumerable<> (4 items) | ||||||||||||
| Project | Branch | Parent | Version | DateCreated | Owner | ChildBranches | ||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| $/Project1 | /Release v1.1.0.0 | /Main | 14 | 04/07/2012 9:18:01 PM | Domain\Pascal |
| ||||||
| $/Project1 | /Main | 8 | 28/06/2012 10:24:05 PM | Domain\Pascal |
| |||||||
| $/Project2 | /Team | /Main | 13 | 04/07/2012 9:17:24 PM | Domain\Pascal |
| ||||||
| $/Project2 | /Main | 12 | 04/07/2012 9:17:02 PM | Domain\Pascal |
| |||||||
| 47 | ||||||||||||
Wednesday, July 4, 2012
TFS Queries: Generating a changelog from the branch history
For an intro on LinqPad and the TFS API please read this post
For the list of all the posts in this series please read this one
If you ever need to produce a changelog for a release you could do it by hand, looking at all the work items associated with the changesets or you could use the TFS API to generate it automatically.
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.VersionControl.Client
Microsoft.TeamFoundation.WorkItemTracking.Client
With this we will get the list of all the changesets and associated work items from the history of the given branch.
For the list of all the posts in this series please read this one
Context
If you ever need to produce a changelog for a release you could do it by hand, looking at all the work items associated with the changesets or you could use the TFS API to generate it automatically.
Required references
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Common
Microsoft.TeamFoundation.VersionControl.Client
Microsoft.TeamFoundation.WorkItemTracking.Client
Query (C# Statements)
var branch = "$/Project1/Main";
var fromVersion = new ChangesetVersionSpec(1);
var toVersion = VersionSpec.Latest;
var tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection(new Uri("http://localhost:8088/tfs"));
tfs.EnsureAuthenticated();
var versionControl = tfs.GetService<VersionControlServer>();
var history = versionControl.QueryHistory(branch, VersionSpec.Latest, 0,
RecursionType.Full, null, fromVersion, toVersion, int.MaxValue, false,
false, false);
history.OfType<Changeset>()
.Select(x => new
{
x.ChangesetId,
x.CreationDate,
x.Committer,
x.Comment,
WorkItems = x.WorkItems.Select(wi => new
{
wi.Id,
wi.Title,
wi.Description,
wi.State,
wi.Reason
})
})
.Dump("Branch history of: " + branch +
" from " + fromVersion.DisplayString + " to " + toVersion.DisplayString);
history.OfType<Changeset>()
.OrderBy(x => x.ChangesetId)
.SelectMany(x => x.WorkItems)
.Select(wi => string.Format("[{0}] {1} #{2} - {3}",
wi.Reason, wi.Type.Name, wi.Id, wi.Title))
.Dump("Changelog of branch: " + branch +
" from " + fromVersion.DisplayString + " to " + toVersion.DisplayString);
Result
With this we will get the list of all the changesets and associated work items from the history of the given branch.
| Branch history of: $/Project1/Main from C1 to T | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Changelog of branch: $/Project1/Main from C1 to T | |||
|---|---|---|---|
|
Wednesday, June 20, 2012
NuGet integration in LinqPad
NuGet is amazing in Visual Studio. With it I can easily download and add references to popular libraries in my project with only a few clicks in Manage NuGet Packages or keystrokes when using the Package Manager Console. I really like that because I can try out new libraries without too much effort. I also like LinqPad to try out snippets of code. But if I want to try a library I have to download the binaries from a web site, unzip them on my disk and finally add references to the assemblies from my query before I can start to play around with it.
The new version of LinqPad (v4.42.04 currently still in beta) finally gets an integration with NuGet directly in the tool but only with the Premium Edition. Let's take a look at how it works.
In the Query Properties (F4) we have a new option: Add NuGet...
This will open the NuGet Manager window
On the left we can see all the NuGet packages we already downloaded. Those will be stored in our local AppData folder and be available for all queries. In the middle section we have the NuGet feed search where we can browse for packages to download. Finally in the section on the right we see all the information on the currently selected package.
To add a package to the current query simply click Add To Query. If the package was not already downloaded LinqPad will do it now and after that it will appear in the left section. Finally we can select namespaces to use in the query by clicking Add namespace.
LinqPad will also automatically check for updates for us so we just have to click Update next to the package. All the queries using this package will get updated to the latest version too.
We are not limited to the official NuGet feed but we could also add new feeds to connect to, even our own if we wish. We can add new feeds by clicking the Settings button in the lower left of the window.
Here we can add a remote feed or a local folder if we wish. After that we'll have the option to choose which feed to use in the main NuGet Manager window using the list down the middle section.
Going back to the Query Properties window all the packages we added will be shown as a reference with the location set to NuGet. If we click on NuGet we can see the current version of the package and an option to Show assemblies in this package.
Here we can exclude some assemblies from the package if we need to.
One additional FREE new feature this time we get in this version is the ability to browse for namespaces to add from existing references. In the Additional Namespace Imports tab click on Pick from assemblies
We can now select one assembly to see the list of available namespaces from it. Then simply select the namespaces we want and click Add Selected Namespaces.
Anyway, hope you get the chance to play with those two together
The new version of LinqPad (v4.42.04 currently still in beta) finally gets an integration with NuGet directly in the tool but only with the Premium Edition. Let's take a look at how it works.
In the Query Properties (F4) we have a new option: Add NuGet...
This will open the NuGet Manager window
On the left we can see all the NuGet packages we already downloaded. Those will be stored in our local AppData folder and be available for all queries. In the middle section we have the NuGet feed search where we can browse for packages to download. Finally in the section on the right we see all the information on the currently selected package.
To add a package to the current query simply click Add To Query. If the package was not already downloaded LinqPad will do it now and after that it will appear in the left section. Finally we can select namespaces to use in the query by clicking Add namespace.
LinqPad will also automatically check for updates for us so we just have to click Update next to the package. All the queries using this package will get updated to the latest version too.
We are not limited to the official NuGet feed but we could also add new feeds to connect to, even our own if we wish. We can add new feeds by clicking the Settings button in the lower left of the window.
Here we can add a remote feed or a local folder if we wish. After that we'll have the option to choose which feed to use in the main NuGet Manager window using the list down the middle section.
Going back to the Query Properties window all the packages we added will be shown as a reference with the location set to NuGet. If we click on NuGet we can see the current version of the package and an option to Show assemblies in this package.
Here we can exclude some assemblies from the package if we need to.
One additional FREE new feature this time we get in this version is the ability to browse for namespaces to add from existing references. In the Additional Namespace Imports tab click on Pick from assemblies
We can now select one assembly to see the list of available namespaces from it. Then simply select the namespaces we want and click Add Selected Namespaces.
Summary
I know that not everyone have the Premium version of LinqPad but still I wanted to show you what appends when 2 amazing productivity tools collide! I guess it is possible to use some NuGet Powershell cmdlet to do part of the job. It think a stand alone NuGet client could be a good idea for someone to come up with too.Anyway, hope you get the chance to play with those two together
Saturday, June 9, 2012
TFS Queries: Build agents status and build queue
For an intro on LinqPad and the TFS API please read this post
For the list of all the posts in this series please read this one
Sometimes it's hard to figure out exactly why a build is pending and not running right after it was queued. It can be because the build agents are currently busy building other builds, or because build agents are not started or even because the windows services for the build agents are not running. Looking at the Build Explorer we can only see builds from one team project at a time which is not ideal when you have a lot of them.
Fortunately we can create a LinqPad query to get all this information in one report.
Microsoft.TeamFoundation.Build.Client
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Framework.Client
System.ServiceProcess
We get a list of the build agents status. Then the state of the windows services running the build agents. Finally the full content of the build queue regardless of the team project.
For the list of all the posts in this series please read this one
Context
Sometimes it's hard to figure out exactly why a build is pending and not running right after it was queued. It can be because the build agents are currently busy building other builds, or because build agents are not started or even because the windows services for the build agents are not running. Looking at the Build Explorer we can only see builds from one team project at a time which is not ideal when you have a lot of them.
Fortunately we can create a LinqPad query to get all this information in one report.
Required references
Microsoft.TeamFoundation.Build.Client
Microsoft.TeamFoundation.Client
Microsoft.TeamFoundation.Framework.Client
System.ServiceProcess
Query (C# Statements)
var tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection(new Uri("http://localhost:8088/tfs"));
tfs.EnsureAuthenticated();
var buildServer = tfs.GetService<IBuildServer>();
var queryAgents = buildServer.QueryBuildAgents(buildServer.CreateBuildAgentSpec());
queryAgents.Agents
.Select(x => new
{
x.MachineName,
Controller = x.Controller.Name,
x.Enabled,
x.Status,
x.QueueCount
})
.Dump("TFS build agents");
queryAgents.Agents
.SelectMany(x => ServiceController.GetServices(x.ServiceHost.Name)
.Where(s => s.ServiceName.StartsWith("TFSBuildServiceHost")))
.Select(x => new
{
x.MachineName,
x.ServiceName,
x.Status
})
.Dump("Windows Services of build agents");
buildServer
.QueryQueuedBuilds(buildServer.CreateBuildQueueSpec("*"))
.QueuedBuilds
.Select(x => new
{
x.TeamProject,
BuildDefinition = x.BuildDefinition.Name,
x.QueuePosition,
x.QueueTime,
x.Priority,
x.CustomGetVersion,
x.RequestedFor,
x.Reason,
x.Status
})
.OrderBy(x => x.QueuePosition)
.Dump("Queued builds");
Result
We get a list of the build agents status. Then the state of the windows services running the build agents. Finally the full content of the build queue regardless of the team project.
| TFS build agents | |||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| |||||||||||||||||||||||||
| Windows Services of build agents | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||
| Queued builds | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||
Wednesday, May 16, 2012
TFS Queries: Recent builds of all team projects
For an intro on LinqPad and the TFS API please read this post
For the list of all the posts in this series please read this one
We can see all the build results of a team project easily inside Team Explorer or with the Web Access but there is no way to see the build results of all team projects at the same time. Using a simple query and a few Linq operators we can get a useful little report in LinqPad.
Microsoft.TeamFoundation.Build.Client.dll
Microsoft.TeamFoundation.Client.dll
Microsoft.TeamFoundation.Framework.Client.dll
You will get a list of the build results of all the team projects for the last week. The total build time is at the top of list. Each build result include the build errors, warnings and the number of StyleCop and FxCop violations found (if you have included those static analysis tools in your project template). Also, on line 9 you can change the query to get build results over a longer period of time.
For the list of all the posts in this series please read this one
Context
We can see all the build results of a team project easily inside Team Explorer or with the Web Access but there is no way to see the build results of all team projects at the same time. Using a simple query and a few Linq operators we can get a useful little report in LinqPad.
Required references
Microsoft.TeamFoundation.Build.Client.dll
Microsoft.TeamFoundation.Client.dll
Microsoft.TeamFoundation.Framework.Client.dll
Query (C# Statements)
var tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection(new Uri("http://localhost:8088/tfs"));
tfs.EnsureAuthenticated();
var buildServer = tfs.GetService<IBuildServer>();
var spec = buildServer.CreateBuildDetailSpec("*");
spec.MinFinishTime = DateTime.Now.Subtract(TimeSpan.FromDays(7));
spec.MaxFinishTime = DateTime.Now;
spec.QueryDeletedOption = QueryDeletedOption.IncludeDeleted;
var builds = buildServer.QueryBuilds(spec).Builds;
var total = builds.Sum(b => b.FinishTime.Subtract(b.StartTime).TotalMinutes);
builds.Select(x => new
{
Project = x.TeamProject,
Definition = x.BuildDefinition.Name,
Version = x.SourceGetVersion,
Developer = x.RequestedFor,
Type = x.Reason,
Start = x.StartTime,
Duration = x.FinishTime.Subtract(x.StartTime),
Build = x.CompilationStatus,
Tests = x.TestStatus,
Result = x.Status,
StyleCopViolations = InformationNodeConverters.GetBuildWarnings(x)
.Count(inc => inc.Message.StartsWith("SA")),
FxCopViolations = InformationNodeConverters.GetBuildWarnings(x)
.Count(inc => inc.Message.StartsWith("CA")),
Warnings = InformationNodeConverters.GetBuildWarnings(x)
.Select(inc => inc.Message)
.Where(m => !m.StartsWith("SA") && !m.StartsWith("CA")),
Errors = InformationNodeConverters.GetBuildErrors(x)
.Select(inc => inc.Message)
})
.OrderByDescending(b => b.Start)
.Dump("All builds of the week. Total build duration: " + total);
Result
You will get a list of the build results of all the team projects for the last week. The total build time is at the top of list. Each build result include the build errors, warnings and the number of StyleCop and FxCop violations found (if you have included those static analysis tools in your project template). Also, on line 9 you can change the query to get build results over a longer period of time.
| All builds of the week. Total build duration: 20.666666666666667 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Subscribe to:
Posts (Atom)




