Unit testing is fairly well defined and accepted in the software development community but automated User Acceptance Tests (UATs) are not widely used and can be difficult to implement. NUnitforms is a automated testing framework that some teams at Varian Australia use as a low level component of an UAT framework.
TO DO - work in progressAutomated Testing
While unit testing is fairly well understood, it is often used to cover the wider scope of integration tests and UATs. This can lead to confusion and loss of focus on what is really required. So the following section describe what these types are tests are.
For the exercise take a simple form that has a button that increments a value.
A simplistic implementation, where the business code is implemented in the Visual Studio generated form class, is shown below.
public partial class MyForm : Form { private int count = 0; public MyForm() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { count++; label1.Text = count.ToString(); } }
Unit Tests
The sample code shown above is not, as shown, unit testable. The reason is that the only way to exercise the code is via another framework (.Net Forms). "Unit testing" means testing code in isolation. Here the code to be tested is a private method accessed via an event from the .Net framework. It cannot be tested in isolation.
To make the code unit testable it must first be split. The common method of doing this is to use the model-view-controller pattern where the code we are interested in is moved to a controller class and the view (form in this case) is made as thin as possible. The view class is not unit tested as it is mostly auto generated by Visual Studio and is just wiring anyway. Its testing will be left for the UATs.
The view:
public partial class MyForm : Form, IMyForm { private IMyFormController controller; public MyForm() { InitializeComponent(); } public void InjectController(MyFormController viewController) { controller = viewController; } private void button1_Click(object sender, EventArgs e) { controller.OnIncrementButtonClicked(); } public void SetLabel(string text) { label1.Text = text; } } public interface IMyForm { void SetLabel(string text); }
Now the form class (view) does not contain any business code. It has just become 'wiring' of a button click out to the business logic in a controller class. The addition of an interface will allow the controller class to be tested in isolation (that is, unit tested).
The controller:
public class MyFormController : IMyFormController { private int count; private readonly IMyForm view; public MyFormController(IMyForm view) { this.view = view; } public void OnIncrementButtonClicked() { count++; view.SetLabel(count.ToString()); } } public interface IMyFormController { void OnIncrementButtonClicked(); }
TO DO
Integration Tests
TO DO
User Acceptance Tests (UATs)
TO DO
Child pages: