-
Get a monthly update on best practices for delivering successful software.
My post today comes after watching the code coverage hover just over 70%, constantly asking myself is it possible to get

100% coverage and a discuss with a few internal colleagues on the subject. Interesting to know is if I exclude the views from code coverage, I hit a high of just over 90%. So, is not testing your UI the end of the world? Not at all, as long as you use good development practices and aim to make your UI as slim as possible, without any business processing, branching or conditional type logic.
I've been very pleased with using the PureMVC framework on my current project, and haven't running into any Ah! Ha! I gotcha scenarios yet and frankly can't envision any as we continue to add new features to this application. In fact using PureMVC has helped me think more about testability of our code and its single messaging bus has been just what the doctor ordered in terms of eliminating Publishing/Subscribing to events between the various components of the system, namely Mediators, Proxies and Commands. But with great power comes great responsibility.
One could easily access the Singleton Facade of the PureMVC framework directly from your view and send a system wide message to any component interested in that message. The problem here is testability of the UI event required to trigger that system notification.
For instance in the code snippet below you would have to create an instance of the UpgradeView and simulate a click of the download button in order to test sending this notification.
public parital class UpgradView :Form, IUpgradeView
{
...
private void DownloadButton_Click(object sender, EventArgs e)
{
Facade.SendNotificaiton("DownloadUpgrade");
}
}
A better approach here is to allow your view to publish events that its mediator can subscribe to. This way you could add more logic before/after sending the notification and makes your code more testable.
public parital class UpgradView :Form, IUpgradeView
{
...
public event EventHandler OnDownLoad;
private void DownloadButton_Click(object sender, EventArgs e)
{
if(OnDownload != null)
OnDownload(this, e);
}
}
public class UpgradMediator : Mediator
{
public UpgradeMediator(IUpgradeView view)
{
view.OnDownload += Download;
}
private void Download(object sender, EventArgs e)
{
// Add more logic here,
Facade.SendNotificaiton("DownloadUpgrade");
}
}
[TestFixture]
public class UpgradMediatorTest()
{
...
public void HandleNotification(INotification notification)
{
switch (notification.Name)
{
case Notification.DownloadNewVersion:
Assert.IsNull(notification.Body);
break;
default:
Assert.Fail();
break;
}
}
[Test]
public void DownloadUpgradeTest()
{
upgradeView.BackToRecord();
upgradeView.Expect(x => x.CloseView()).Repeat.Once();
upgradeView.OnDownloadUpgrade += null;
IEventRaiser eventRaiser = LastCall.IgnoreArguments().GetEventRaiser();
upgradeView.Replay();
UpgradeMediator mediator = new UpgradeMediator(upgradeView);
eventRaiser.Raise(this, EventArgs.Empty);
upgradeView.VerifyAllExpectations();
}
}
So its it possible to get 100% coverage or is 100% just some pie in the sky that we aim for. Frankly, 90%+ code coverage aint bad, especially when my views are lean mean fighting machines. Ok one last thing I'm sure your wondering is why not 100% coverage now that the views are excluded. Well, smarty pants, I can't test external third party APIs code that we include, nor do I want to.
Related Services: .Net Application Development,
Custom Software Development
Related posts:
Topics: .NET, Pure MVC, PureMVC, user interface