In the previous section, we created the unit testing Solution
folder within our TrackMyWalks
main project solution that will be used to separate the unit tests from our main iOS and Android project solutions. This is so that we can run these independently from the main solution.
One of the great benefits of using Xamarin Studio to handle your tests is that it leverages the popular NUnit testing framework for performing unit tests. We will begin by creating the NUnit test project within the TrackMyWalks.Tests
solution that we've previously created.
Let's start by creating a new NUnit project within our TrackMyWalks.Tests
project solution, by performing the following steps:
TrackMyWalks.Tests
solution project and choose the Add | Add New Project... menu option, as shown in the following screenshot:
TrackMyWalks.UnitTests
to use as the name for your new project in the Project Name field.
Once your project has been created, you will be presented with the Xamarin Studio development environment, with your new projected created within the TrackMyWalks.Tests
solution folder.
In the next section, we will begin to add the Moq (pronounced as mock) framework library that will be responsible for allowing us to test our ViewModels
within the TrackMyWalks
solution.
Now that you have set up and created a new unit test project, our next step is to add the Moq (pronounced as Mock) NuGet package to the TrackMyWalks.UnitTests
solution. This library is essentially one of the most popular and friendly mocking framework libraries for the .NET platform, and we will use this to test some of our ViewModels
within our TrackMyWalks
app.
Let's look at how to add the Moq NuGet package to our TrackMyWalks.UnitTests
project solution, by performing the following steps:
Packages
folder that is contained within the TrackMyWalks.UnitTests
solution, and choose the Add Packages... menu option, as shown in the following screenshot:
moq
within the search dialog, and select the Moq: an enjoyable mocking library option within the list, as shown in the following screenshot:
NuGet
package to the Packages
folder contained within the TrackMyWalks.UnitTests
solution.In the previous section, we added the Moq NuGet package to our TrackMyWalks
solution. The next step is to add a reference to the TrackMyWalks
core library to our TrackMyWalks.UnitTests
solution.
Since we will be testing our ViewModels
, you will need to ensure that you have applied all of the cumulative code changes to the TrackMyWalks
solution project throughout this book to avoid any issues, as we will essentially need to break each of the tests into individual classes representing each ViewModel and the accompanying unit test class that we want to test the business logic on. To successfully test our ViewModels
, we will first need to include a reference to the TrackMyWalks
project within our TrackMyWalks.UnitTests
solution project.
Let's look at how we can achieve this, by performing the following steps:
References
folder that is contained within the TrackMyWalks.UnitTests
project solution, and choose the Edit References... menu option, as shown in the following screenshot:
TrackMyWalks.UnitTests
project solution:
TrackMyWalks
project within the Projects tab, click on OK to add the project reference to your References
section of your TrackMyWalks.UnitTests
project solution, and close the Edit References dialog.In the next section, we will begin by creating our first unit test which will be responsible for validating the WalkEntry
model to ensure that after the ViewModel has been initialized, it will contain walk information.
Now that you have incorporated the TrackMyWalks
project into the TrackMyWalks.UnitTests
solution, our next step is to create the unit test for our WalksTrailViewModel
. These tests will be used to help us check to see when our ViewModel passes or fails under these test conditions.
Let's now start to implement the code required for our WalksTrailViewModelTest
class, by performing the following steps:
TrackMyWalks.UnitTests
project solution folder, by choosing Add | New File.... If you can't remember how to do this, you can refer to the section entitled Creating the TrackMyWalks model, within
Chapter 1
, Creating the TrackMyWalks Native App.WalksTrailViewModelTest
for the name of the new class that you want to create, and click on the New button to allow the wizard to proceed and create the new file.WalksTrailViewModelTest.cs
file is displayed within the code editor, and enter in the following code snippet:// // WalksTrailViewModelTest.cs // WalksTrailViewModel Testing Framework // // Created by Steven F. Daniel on 23/09/2016. // Copyright © 2016 GENIESOFT STUDIOS. All rights reserved. // using NUnit.Framework; using TrackMyWalks.ViewModels; using TrackMyWalks.Services; using Moq; using System.Threading.Tasks; namespace TrackMyWalks.Tests {
WalksTrailViewModelTest
class constructor by adding the [TestFixture]
attribute which sets up our class to be an instance of the TestFixture
testing class. Proceed and enter in the following code snippet:[TestFixture] public class WalksTrailViewModelTest { WalksTrailViewModel _vm;
Setup
instance method that will be responsible for creating a new instance of our ViewModel for each of the tests that are declared within the class. This is to ensure that each test is run using a clean instance of the ViewModel. We then proceed to declare a navMock
variable instance of the Mock
class from our Moq library to create a new instance of the IWalkNavService
and instantiate the WalksTrailViewModel
, using the navMock
instance. Proceed and enter in the following code snippet:[SetUp] public void Setup() { var navMock = new Mock<IWalkNavService>().Object; _vm = new WalksTrailViewModel(navMock); }
CheckIfWalkEntryIsNotNull
instance method that will check to see if our WalksTrailViewModel
has been properly initialized when the Init
method is called. We declare the [Test]
attribute which is essentially an abstract class that represents a test within the NUnit.Test
framework. We proceed to initialize our WalkEntry
model to null
, and then call the Init
method to check to see if the WalkEntry
model has been properly set to the value provided in the Init
method's parameter and then use the IsNotNull
method on the Assert
class to display a message should the test fail. This is so that you can troubleshoot the code at a later point. Proceed and enter in the following code snippet:[Test] public async Task CheckIfWalkEntryIsNotNull() { // Arrange _vm.WalkEntry = null; // Act await _vm.Init(); // Assert Assert.IsNotNull(_vm.WalkEntry, "WalkEntry is null after being initialized with a valid WalkEntries object."); } } }
In the preceding code snippet, we began by implementing the various instance methods that will be required to perform each test for our WalksTrailViewModel
. We added the [TestFixture]
attribute at the beginning of our class constructor so that it will be an instance of the TestFixture
testing class. We then proceeded to create the Setup
instance method so that it will be responsible for creating a new instance of our ViewModel for each of the tests that are declared within the class, using the [Test]
attribute. This is essentially an abstract class that represents a test within the NUnit.Test
framework, and ensures that each test is run using a clean instance of the ViewModel.
Next, we used the Mock
class from our Moq library to create a new instance of the IWalkNavService
when instantiating the WalksTrailViewModel
.
In the next step, we implemented the CheckIfWalkEntryIsNotNull
instance method that will perform a check to see if our WalksTrailViewModel
has been properly initialized whenever the Init
method has been called. Again, we declared the [Test]
attribute prior to initializing our WalkEntry
model to null
, and prior to calling the Init
method to check to see if the WalkEntry
model has been properly set to the value provided in the Init
method's parameter. After that, we used the IsNotNull
method on the Assert
class to display a message should the test fail. This is so that you can troubleshoot the code at a later point.
In the next section, we will begin by creating the second unit test which will be responsible for validating information contained within our WalkEntryViewModel
to ensure that after our ViewModel has been initialized, we receive the expected results returned.
In the previous section, we created the NUnit test for our WalksTrailViewModel
which checked to ensure that the WalksEntry
model was properly initialized after the Init
method was called. In this section, we will create another NUnit test that will check to see if certain properties within our WalksEntryViewModel
have been set up and initialized.
Let's now start to implement the code required for our WalkEntryViewModelTest
class by performing the following steps:
TrackMyWalks.UnitTests
project solution folder, by choosing Add | New File.... If you can't remember how to do this, you can refer to the section entitled Creating and implementing the WalksTrailViewModel NUnit test class, within this chapter.WalkEntryViewModelTest
for the name of the new class that you want to create, and click on the New button to allow the wizard to proceed and create the new file.WalkEntryViewModelTest.cs
file is displayed within the code editor, and enter in the following code snippet:// // WalkEntryViewModelTest.cs // WalkEntryViewModel Testing Framework // // Created by Steven F. Daniel on 23/09/2016. // Copyright © 2016 GENIESOFT STUDIOS. All rights reserved. // using NUnit.Framework; using TrackMyWalks.ViewModels; using TrackMyWalks.Services; using Moq; using System.Threading.Tasks; namespace TrackMyWalks.UnitTests {
WalkEntryViewModelTest
class constructor by adding the [TestFixture]
attribute just as we did in the previous section. This sets up our class to be an instance of the TestFixture
testing class. Proceed and enter in the following code snippet:[TestFixture] public class WalkEntryViewModelTest { WalkEntryViewModel _vm;
Setup
instance method that will be responsible for creating a new instance of our ViewModel for each of the tests that are declared within the class. This is to ensure that each test is run using a clean instance of the ViewModel. We then use the Mock
class from our Moq library to create a new instance of the IWalkNavService
when instantiating the WalkEntryViewModel
. Proceed and enter in the following code snippet:[SetUp] public void Setup() { var navMock = new Mock<IWalkNavService>().Object; _vm = new WalkEntryViewModel(navMock); }
CheckIfEntryTitleIsEqual
instance method that will check to see if our Title
property has been properly initialized when the Init
method has been called. We'll declare the [Test]
attribute just as we did in the previous test, and then we'll proceed to initialize the Title
property and call the Init
method to check whether the Title
property has been initialized correctly to the value provided in the Init
method's parameter.AreEqual
method on the Assert
class to check to see if the Title
property has been initialized correctly, and then display a message containing the value of the Title
property from the ViewModel, should the test fail. Proceed and enter in the following code snippet:[Test] public async Task CheckIfEntryTitleIsEqual() { // Arrange _vm.Title = "New Walk"; // Act await _vm.Init(); // Assert Assert.AreEqual("New Walk", _vm.Title); }
CheckIfDifficultyIsEqual
instance method and declare the [Test]
attribute, prior to initializing our Difficulty
property to a string value, and then calling the Init
method. In the next step, we use the AreEqual
method on the Assert
class to check whether the Difficulty
property has been initialized correctly, and display a message containing the value of the Difficulty
property from the ViewModel, should the test fail. Proceed and enter in the following code snippet:[Test] public async Task CheckIfDifficultyIsEqual() { // Arrange _vm.Difficulty = "Easy"; // Act await _vm.Init(); // Assert Assert.AreEqual("Easy", _vm.Difficulty); }
CheckIfKilometersIsNotEqual
instance method that declares the [Test]
attribute just as we did in the previous test. We then initialize our Kilometers
property to a Double
value, and call the Init
method. In the next step, we use the AreEqual
method on the Assert
class to check to see if the Kilometers
property has been initialized correctly, and display a message containing the value of the Kilometers
property from the ViewModel
, should the test fail. Proceed and enter in the following code snippet:[Test] public async Task CheckIfKilometersIsNotEqual() { // Arrange _vm.Kilometers = 40.0; // Act await _vm.Init(); // Assert Assert.AreNotEqual(40.0, _vm.Kilometers); } } }
In the preceding code snippet, we began by implementing the various instance methods that will be required to perform each test for our WalkEntryViewModel
. We added the [TestFixture]
attribute at the beginning of the class constructor so that it will be an instance of the TestFixture
testing class; and then proceeded to create the Setup
instance method so that it will be responsible for creating a new instance of our ViewModel for each of the tests that is declared within the class, using the [Test]
attribute which is essentially an abstract class that represents a test within the NUnit.Test
framework, and ensures that each test is run using a clean instance of the ViewModel.
Next, we used the Mock
class from our Moq library to create a new instance of the IWalkNavService
when instantiating the WalkEntryViewModel
. In the next step, we implemented the CheckIfEntryTitleIsEqual
instance method that will perform a check to see if the Title
property has been properly initialized whenever the Init
method has been called. Again, we declare the [Test]
attribute prior to initializing the Title
property of the WalksEntry
model, and prior to calling the AreEqual
method on the Assert
class to check to see if the Title
property has been initialized correctly. We then displayed a message containing the value of the Title
property from the ViewModel, should the test fail.
Next, we implemented the CheckIfDifficultyIsEqual
instance method that will initialize the Difficulty
property to a string value, and then call the Init
method of the WalkEntryViewModel
. We called the AreEqual
method on the Assert
class to confirm that, after we call the Init
method, the value of the Difficulty
property from the ViewModel is the value that we expect to come back from the provided Mock
instance. If the value is not what we expect, the test will fail and will display a message containing the value of the Difficulty
property from the ViewModel
.
In our final step, we implemented the CheckIfKilometersIsNotEqual
instance method that initializes our Kilometers
property to a Double
value, and then calls the Init
method. Just as we did in our CheckIfDifficultyIsEqual
instance method, we used the AreNotEqual
method on the Assert
class to confirm that, after we call the Init
method, the value of the Kilometers
property from the ViewModel is the value that we expect to come back from the provided mock instance. If the value is not what we expect, the test will fail and will display a message containing the value of the Kilometers
property from the ViewModel.
For each test method that you create that will be represented by the NUnit [Test]
attribute, the Arrange-Act-Assert pattern will follow. This is described in the following table:
Test pattern |
Description |
Arrange |
This will essentially perform all the setting up and initialization conditions for your test. |
Act |
This ensures that your test will successfully interact with the application. |
Assert |
This will examine the results of the actions that were initially performed within the Act step to verify the results. |
You can now see, that by incorporating the NUnit.Framework
within your applications, as well as adopting the Arrange-Act-Assert pattern, you can essentially perform tests on your ViewModels to ensure that the results you are expecting are returned.
If you are interested in learning more about the NUnit.Framework.Test
class, and its associated methods, please refer to the information contained at
https://developer.xamarin.com/api/type/NUnit.Framework.Internal.Test/
.
To learn more about the NUnit.Framework.Assert
class and other methods that you can use to handle the different types of assertions, please refer to the information located at
https://developer.xamarin.com/api/type/NUnit.Framework.Assert/
.
Now that you have created your unit tests, our next step is to begin running our tests right within the Xamarin Studio IDE, which we will be covering in the next section.
In our previous section, we created and implemented unit tests for both the WalksTrailViewModel
and the WalkEntryViewModel
. These contained sets of various test conditions that we checked against.
Our next step is to begin running these unit tests directly from within the Xamarin Studio development environment.
Let's look at how we can achieve this with the following steps:
TrackMyWalks.UnitTests
project within the Solution pane, and choose the Run Item option, as shown in the following screenshot:
TrackMyWalks.UnitTests
solution project and then navigating to the Run menu option and choosing the Run Unit Tests sub-menu item.When the compilation of the unit tests has completed, you will be presented with a list showing each of your test results that have passed, failed, or were ignored. These are displayed within the Test Results pane, as shown in the following screenshot:
Should any of your tests fail, these will be displayed within the Test Results pane, along with their associated Stack Trace. You will also notice that the message that we provided within the Assert.AreEqual
method will also be displayed as part of the failure result:
From this screen, you have the option of filtering your test results or re-running your unit test conditions again. These are explained in more detail in the following table:
Test result option |
Description |
Successful Tests |
This will display all the successfully executed tests which passed the conditions as specified within the test case. |
Inconclusive Tests |
This will display any test results that were found to be inconclusive, meaning that a firm result could not be determined. |
Failed Tests |
This option displays a list of any tests that did not meet the conditions as specified within the test case scenario. |
Ignored Tests |
This option displays a list of any tests that were ignored as specified by the |
Output |
This option displays a console output for each of the tests that are executed and will contain any tests that have successfully passed, failed, been ignored, or were found to be inconclusive. |
Rerun Tests |
This option enables you to re-run your tests again, without the need for recompiling your test cases. |
Now that you have a good understanding of how to create your own unit tests using the NUnit testing framework, we can now look at how to create another form of unit testing, which is called automated UI testing. This time we will be leveraging the UITest framework which will enable us to perform tests on the user interface portion of our TrackMyWalks
app which we will be covering over the next sections.
3.142.42.176