XR Developer’s view on Unit Testing— Part 1

Poornaprasad V
XRPractices
Published in
3 min readApr 18, 2020

--

Unit testing, a testing technique using which individual units/components of the software are tested to determine if there are any issues by the developer himself. Every developer should test their code before it goes to production.

I used C# heavily in my recent XR projects and found unit a great helper for me in producing better quality of code and be confident on what you have written, I no more fear of refactoring, and living any issues in my well-tested code. Here I am sharing my learning from test-driven development in C#.

Benefits of writing Unit tests:

  • Improves the quality of code
  • Finds bug ahead
  • Simplifies the debugging process
  • Provides the documentation of the API’s
  • Reduce the cost of the stakeholders since the bugs are found prior

Characteristics of a good unit test

First-class citizen

They are important if not more than the production code that means all the good practice of writing clean, readable and maintainable code applies for the test as well and they should have a single responsibility. The test acts as a documentation of your code.

No Logic

The unit test should not have any conditional statement, for loop in the test, if it has it is possible that your test will have a bug and that test will fail and you think there is a problem in production code and after spending more time, so no logic in the test

Isolated

Each test should be written and executed as if that is the only test, your test method should not call each other and should not assume any state saved by the another test

Core unit testing techniques

Here I am covering some core unit testing techniques where we find difficulties in writing tests

Consider a simple class with a log method that sets the last error property of that class

using System;
class ErrorLogger {
public string lastError{get; set;}
public event EventHandler<Guid> ErrorLogged;
public void Log(string error){
if(String.isNullOrWhiteSpace(erro)){
throw new ArgumentNullException();
}
lastError=error
ErrorLogged?.Invoke(this,Guid.NewGuid());
}
}

Testing the Void Method

There are two types of function in programming, query functions which return some value and command function which are supposed to perform some action. The void method by definition is a command function. Command function may change a state of an object, change the state of one or more properties or preserve some states. In the tests when a void method is called, we can assert the properties that are changed by this method.

Test case

using NUnit.Framework;using TestNinja.Fundamentals;
[TestFixture]
public class ErrorLoggerTests{
[Test]
public void ShouldSetTheLastErrorPropertyWhenLogMethodIsCalled()

{
var logger = new ErrorLogger()
logger.Log("a");
Assert.That(logger.LastError , Is.EqualTo("a"));
}
}

Testing methods that throw Exceptions

To write an assertion for a method that throws an exception is by using a delegate. For the above class that we are testing, if the error is null or empty it throws an exception. There are three test cases for the above scenario, if the error is a null or empty string (“”) or empty string with space (“ <space>”). Here I am using parameterized testing to reduce the number of lines.

[Test]
[TestCase(null)]
[TestCase("")]
[TestCase(" ")]
public void ShouldThrowExceptionWhenErrorIsNullOrEmptyStringOrEmptyStringWithSpaceWhenLogMethodIsCalled(string error){
var logger = new ErrorLogger();
Assert.That(() =>
logger.Log(error),Throws.ArgumentNullException);
}

Testing methods that raise an Event

We need to subscribe to the Event in the test before we call the method that raises the event and we can assert that the event is raised with the particular argument

[Test]
public void ShouldRaiseAnEventWithNewGuidOnVaildErrorWhenLogMethodIsCalled(){
var logger = new ErrorLogger();
var id = Guid.Empty;
logger.ErrorLogged += (sender,args) => { id = args; };
logger.Log("a"); Assert.That(id,Is.Not.EqualTo(Guid.Empty));
}

In the next part, we will be seeing how to break the external dependencies, Mocking, testing on private methods.

--

--