Tag Archives: software development

How to Write Unit Tests in .NET

Unit testing is the idea of writing a separate set of code to automatically execute your production code and verify the results. It’s called a ‘unit’ test because the idea is that you are only testing a single ‘unit’ of code and not the entire application. Writing Unit Tests is often seen in Test Driven Development but can and should be used in any development environment.

Unit tests give your application increased testing coverage with very little over-head. Most unit tests can execute extremely fast which means you can write hundreds of them and execute them all relatively quickly. In environments with multiple developers, unit tests can provide a sanity check for other developers making changes to existing code. But how do we actually go about writing a unit test?

Advertisements

In .NET there’s a couple of ways we can do this. In Test Driven Development, you write your tests first. That sounds backwards but it’s really about teaching your mind to think a certain way before you start writing any code because to write unit tests, you need highly decoupled code with few dependencies. When you do have dependencies you’ll want to use Dependency Injection (which we can cover at another time).

The .NET stack provides a built in testing harness called MSTest. It gets the job done but doesn’t come with the bells and whistles. I personally prefer xUnit which can be downloaded as a Nuget package. There is also NUnit which is very similar but I prefer xUnit because each execution of a test is containerized where as in NUnit all tests are run in a single container.

So once we’ve installed xUnit we can start writing our first tests. The first thing to do is to create a new project in your solution. We can do this by opening up our project in Visual Studio and then right-clicking on our solution, choosing Add, and then new project. From the ‘Add a new project’ window we can search for ‘xUnit Test Project‘ and add that. I simply name the project ‘Test’ and click create.

Advertisements

By default a new class is created which contains your new test class. You should also see the ‘Test Explorer’ window in Visual Studio on the left-hand side. If you don’t, go to the ‘View’ menu and select it. This menu contains all of your tests that you write and allows you to run them all or run them individually. You can also kick off a single test to debug it.

Now the fun part, writing a test! Let’s keep it simple for starters and look at an example test:

[Fact]
public void ItCanAddTwoNumbers()
{
   var result = AddTwoNumbers(1, 4);
   Assert.Equal(5, result);
}

So this test is doing a couple of things. By defining [Fact] we are saying this function is a test function and not some other helper function. I try to name my test functions based around what the application is trying to do like, ‘ItCanAddTwoNumbers’ but that is completely up to you.

Within the test function we can then call the function we want to test which in this case is ‘AddTwoNumbers(int num1, int num2).’ Simply calling this function and making sure the application doesn’t crash or throw an error is already a little bit of test coverage which is great, but we can go farther. We can not only make sure it doesn’t error, we can make sure we get the right results back.

We can do this using ‘Assert‘ which gives us some different options for verifying the results are correct. In this case, our test will check to make sure the ‘result’ variable does equal 5. If it does, our test will pass with green colors. If not, our test will fail and show red in our Test Explorer. This is great when you already have some test written, you make some code changes, and then re-run all of your tests to make sure everything is still working correctly.

One last tip, instead of using [Fact] we can use [Theory] to allow us to pass in multiple test values quickly like this:

[Theory]
[InlineData(2)]
[InlineData(5)]
[InlineData(7)]
public void ItCanAddOneToANumber(int number)
{
    var results = AddOneToNumber(number);
    Assert.Equal(number + 1, results);
}

Hopefully this gives you a brief introduction into how to write Unit Tests in .NET using xUnit. Unit testing will save you hours of debugging and troubleshooting time when that sneaky bug shows up that you can’t quite track down. Even if the bug is not in your unit tests, it can help you track down the issue faster because you’ll know it’s not in any of your code that you have unit tests for.

Always test and happy coding!

What is Site Reliability Engineering?

I was recently asked to move into the role of a Site Reliability Engineer. The only problem was… I didn’t even know what a Site Reliability Engineer was. Over the last few weeks I’ve started to dive in on what Site Reliability Engineering really is, SRE for short, and how to fulfill this role. I’d like to share some of the insights that I’ve gained about the role, what it means, and discuss some of the topics around SRE’s.

The role of an SRE is fairly straight forward on the surface but rather complex and intricate on how it is fulfilled. The job of an SRE is to make sure a website or webservice is reliable. The question is, what does reliability mean?

photo cred: Romson Preechawit

Does it just mean the website is up and running?

Does it mean there are no bugs?

Does it mean it performs well and there’s no latency?

And once you’ve defined what SRE is, how do you accomplish it?

Lots of questions and lots of answers.

SRE’s are sometimes confused with DevOps and some of their functions are very similar and overlap. Both roles favor automation and building internal systems and tools but SRE’s really differ in what they are trying to accomplish.

In DevOps, we want to improve the internal efficiency of our daily development operations, automating builds and unit tests, creating deployment pipelines, and be really focused on the CI/CD pipeline.

Advertisements

For SRE’s, we want to improve the post-CI/CD side of things. Meaning, once things are deployed, we want to make sure they are running smoothly and when they’re not we want to make sure we can get back to a smooth state as quickly as possible. For SRE’s it’s all about monitoring and alerting. Remember the end goal for an SRE is reliability.

Reliability… there’s that word again… so what does it mean for an SRE? Well it actually means a lot of things that come right down to what level of service you provide for your customers. Reliability is more than just, “is the application up and running?” It actually pertains to a wide variety of categories that all come back to how end-users view the quality of your website or webservice.

Here are a few of the categories that fall under the SRE belt:

  • Latency & Response Times
  • Data Quality & Correctness
  • Uptime & Availability
  • Volume & Load
  • Errors & Bugs
photo cred: Chuttersnap

All of these fall under the umbrella of reliability. After all, what good is a website if it slows to a crawl during peak hours? What value does it have if the data is incorrect or invalid? How useful is a website or webservice if it’s filled with bugs after every release?

These are all areas of responsibility for an SRE. Thankfully there are some great tools and best practices to make the life of an SRE easier. Over the next few weeks we’ll dive into some of those practices and tools and discuss how best to implement them. Even if you aren’t an SRE there will be plenty of valuable information and content for you to add to your Software Engineering tool box!

How I Conduct a Code Review

Code reviews have been and always will be tricky business. If you’re familiar with performing code reviews or having someone else review your code, you hopefully can understand and see the benefits. For some though, a code review can be a hit to the ego. Here’s how I’ve approached code reviews and what I find works best.

First and foremost, you have to have some formal code review practices in place. If you don’t, I suggest you start by offering up your services. Not in a way that says, “I’m a better developer and I know more so let me make sure your code is right.” If you give off any type of vibe like this, your code review is going to come off as arrogant and unwanted.

Offer your services for a code review as a means to help take some of the pressure off of the other developer. Your code review is to help them look for bugs, typos, or little details they may have missed. It’s also to provide a challenge back to that person to ask both you and them to think critically.

Once you’re able to agree to a code review with your peer, the next step is actually conducting the review. But how do you go about performing a code review? What should you be looking for? What really works? I follow these same steps, every single time, and find they always hit the nail on the head.

Advertisements

Step 1: Compare

Before I actually do any real review, I start by performing a compare. There are a lot of ways to compare the changes, before and after, and I’ll let you figure that part out. I start with a compare to get a sense of what I’m going to be reviewing.

How much code has changed and how much did it change by? At times I may find that too much has changed, making the review nearly impossible. When this happens, it’s best to recommend that the developer try to create smaller commits. BOOM! You just gave your first piece of code review feedback.

When looking through the compare, don’t try to focus on individual lines of code yet. We’re not at that stage. Stay at a high level and focus on structure and getting familiar with what you’re working with. Are there new classes or functions? Is it a complete rework or just a quick change? Are there unit tests? Did the developer leave any notes for the reviewer? Focus on gathering information and making an initial assessment.

If I suspect that the developer is not done working on an area or that there may be major, additional changes I will stop my review right there on that area. There is no sense in going to the next level of review if the section of code will potentially be refactored or changed. Save yourself some time and simply give the developer your high level assessment and tell them you look forward to diving deeper once they are closer to completing their changes.

photo cred: Pankaj Patel

Step 2: Debug

This is a step I think a lot of inexperienced code reviewers skip over. DEBUG THE F%$*@!+ CODE! For real though, pull the code down, set breakpoints on all of the changes (because you know where they are because you just did a before and after compare on them) and start to debug. I find that it helps me if I just go line-by-line and get an understanding of what each piece is doing.

This is where I really start performing the review. I look for any errors, bugs, or design flaws. I also ask questions about anything I’m unfamiliar with myself. If the developer created Unit Tests I try to either add my own data to those tests or see if I can break them. This helps expose any areas the developer over-looked.

You might be thinking that stepping through each line is not needed or that it’s a lot of extra work but in all honesty it’s not. You can debug a few hundred lines of code in a matter of minutes. Most developers break things out into more lines than what they would ever really need and stepping through that code becomes even easier.

photo cred: Agence Olloweb

Step 3: Feedback

After stepping through every line of code you should be prepared to provide your feedback. When it comes to feedback I find there is really only one good way to do it. Keep it positive and make it suggestive. At the end of the day, the developer who wrote the code has to be responsible for the quality of that code. Often times if you try to force a change in your code review you’ll end up with a You vs Me scenario that isn’t really productive for anyone.

I prefer to start with something positive. I try to take into account the amount of time and effort the developer had to put into their work and look for any design patterns or usage of good programming practices that I can point out right a way. It’s a lot more fun to code review someone’s work when they are using best practices.

For the harder stuff, I try to offer up changes as a suggestion. Unless I see a clear cut bug. If I see a bug or true flaw I try to provide a Unit Test or solid steps to reproduce to help the developer out. After all, we’re all in this together.

If the change is more about design or best practice, then I offer it as a suggestion. I might say, “Hey you could try this technique here to reduce x amount of code” or “If you try this, it can help keep things easier to maintain down the line. Let me know if I can help!” Offering up additional services or help is often a great way to provide feedback.

Advertisements

Step 4: Rinse & Repeat

From there you can send your code review back. Try to capture as much as you can in that first review. It’s much less grueling if you have to go back-and-forth and back-and-forth because you keep only catching one issue at a time. Try to capture all of it, up front, on the first review.

When the code comes back again for a second review. Hopefully all items are addressed and you can pass the review BUT don’t be afraid to go back through steps 1-3. Actually I encourage you to go through them each time, just maybe at a faster pace or a high level. For example, your first pass you should debug every line of code, maybe on your second review you just stick to the areas of change.

Hopefully this gives you a good idea of how to conduct a code review! If you have any personal tips on your best practices for code reviews I’d love to hear them!

The Factory Pattern

In part II of our programming mini-series we’ll dive into the Factory Pattern, how it can be used, and when it can be beneficial.

The Factory Pattern itself is fairly straight forward. When we use the Factory Pattern we are building a Factory that will produce objects for us. There’s two key reasons this pattern is helpful and I’ll share some examples of how we can use it.

First and foremost, the Factory Pattern allows us to encapsulate (wrap and hide) the creation of objects. This means that instead of coding ourselves into a maintenance nightmare where we are instantiating concrete class after concrete class, we can instead code to a single factory and allow it to provide our instantiation. Let’s look at a bad example:

public class LevelOne
{
	public void CreateEnemy(string enemyName)
	{
	   if (enemyName == "HammerBro")
		  HammerBro hammerBro = new HammerBro();
	   else if (enemyName == "BulletBill")
		  BulletBill bulletBill = new BulletBill();
	   else if (enemyName == "PiranhaPlant")
		  PiranhaPlant piranhaPlant = new PiranhaPlant();
	   else if (enemyName == "KoopaTroopa")
		  KoopaTroopa koopaTroopa = new KoopaTroopa();
	   else if (enemyName == "Goomba")
		  Goomba goomba = new Goomba();
	}
}

What you see above is pretty common in Software Development. We need a function that we can tell what kind of enemy we need and it will create it for us. However, this approach comes with a lot of headaches.

Any time we want to add a new enemy we now have to open this class back up and make a change. Anytime we have to make a change to existing code, we’re introducing risk. Now, we’ll have to change this code no matter what if we want to add a new enemy BUT we can do this in a way that reduces our risk and the number of changes we have to make in our application.

Consider that instead our class is used by another development team. Now each time we add a new enemy we have to ask that team to update their create function to be compatible with ours. Now consider this other team is actually a customer or vendor. How easy is it to ask them to make changes every time we make a change?

And let’s say we want this function that creates our enemy to return our enemy so he can do things like attack. We’ll we’re going to need a lot of code and a lot more if statements to do things like:

if (koopaTroopa)
   koopaTroopa.Attack();
else if (goomba)
   goomba.Attack();

The Factory Pattern makes this all go away. It does away with the dependencies on concrete classes, it abstracts the creation of enemies, and it reduces the amount of code that needs changed when new Enemy class are created or changed.

The second benefit we’ll get from our Factory is a centralized place for anyone to get an enemy from. This means that on Level 1 we can use the same factory to create the same enemies as we use on Level 20. We don’t need to re-implement enemy instantiation or repeat any of our enemy code. Woot!

So what can our Factory look like? Well with the help of an Interface it can look like this:

public class EnemyFactory
{
	public IEnemy CreateEnemy(string enemyName)
	{
	   if (enemyName == "HammerBro")
		  return new HammerBro();
	   else if (enemyName == "BulletBill")
		  return new BulletBill();
	   else if (enemyName == "PiranhaPlant")
		  return new PiranhaPlant();
	   else if (enemyName == "KoopaTroopa")
		  return new KoopaTroopa();
	   else if (enemyName == "Goomba")
		  return new Goomba();
	}
}

Now you might say, wait a minute… this looks exactly the same as what we had before. And you’d be right! It’s very close, so let’s take a look at what’s different.

Instead of instantiating the enemy and storing a copy of the concrete class within LevelOne we have abstracted the creation to another class (our Factory!). We’ve also implemented an Interface, think of an interface like wrapping paper around our object, it will allow us to treat the enemy in a generic way. Our interface might look like this:

public interface IEnemy
{
   public void Attack();
}

With our new Factory and Interface we can now flexibly create the enemies we need, have them attack (and perform the correct attack), and our friends on the other development team will love us so much more because they no longer need to refactor and write new code each time a new enemy class is created. Let’s see an example:

public class LevelOne
{
   IEnemy currentEnemy;//our enemy to fight
   
   public LevelOne()
   {
      //create our factory
      EnemyFactory factory = new EnemyFactory();	  
   }
   
   public void CreateGoomba()
   {
      //let our factory create the enemy
      currentEnemy = factory.CreateEnemy("Goomba");
   }
   
   public void AttackPlayer()
   {
      //our interface knows which enenmy Attack() function to call
      enemy.Attack();
   }
}

So what’s so different and special about this design? Well for one, our LevelOne class no longer depends on 6 other enemy classes. If our game designer comes along and decides that, “Oh we want to create a new Goomba class called SuperGoomba” we can now easily make that change on one line of code.

What else is helpful here? Well now we have a single place to go to for enemy creation. Not only can LevelOne create any enemy it wants, so can LevelTwo, and LevelTen, and so on. And if new enemies are added, none of the code needs to change for existing levels.

The final benefit we gain from using the Factory Pattern is the advantage of using interfaces. By allowing our Factory to return an interface instead of a concrete class we can make it much easier for other developers to use our factory. Developers won’t need to code for 6 different Attack() functions for each enemy type. They can instead code a single ‘enemy.Attack()’ function which will allow us to call each enemies Attack() without actually having to know which enemy it is.

In closing, the Factory Pattern is simply a way for us to create a Factory that does all the hard work of creating objects and gives them back to us in a generic fashion by using an Interface. It allows us to decouple our code, encapsulate instantiation, and provide highly maintainable solutions. If you find that you’re using the ‘new’ keyword to create objects it might be a good time to consider using the Factory Pattern.