Skip to main content

What Unit Testing Is

With that out of the way, let’s consider what actually does qualify.  Unit tests isolate and exercise specific units of your code.  Okay.  I’ll concede that I just punted by defining a term with a word in the term.  But the creators of the term left the designation deliberately vague, presumably to cross language boundaries.
In C#, you can think of a unit as a method.  You thus write a unit test by writing something that tests a method.  Oh, and it tests something specific about that method in isolation.  Don’t create something called TestAllTheThings and then proceed to call every method in a namespace.
That’s really it — all there is to it.  You’ll notice that I haven’t mentioned a few things that might pop into your head, such as test-driven development (TDD), unit test frameworks, test runners, mocks, or other unit testing tools.  Let’s not get ahead of ourselves.  Forget TDD and mocks for another time, as those are separate topics.  And forget test runners and frameworks for now.  We will get to those, but they aren’t, strictly speaking, necessary to have a unit test.

What Unit Testing Isn’t
First, let’s clear up any misconceptions by talking about what doesn’t count.  Not every test you could conceivably write qualifies as a unit test.
If you write code that stuffs things into a database or that reads a file from disk, you have not written a unit test.  Unit tests don’t deal with their environment and with external systems to the codebase.  If it you’ve written something that can fail when run on a machine without the “proper setup,” you haven’t written a unit test.
Unit tests also don’t count as other sorts of tests.  If you create some sort of test that throws thousands of requests for a service you’ve written, that qualifies as a smoke test and not a unit test.  Unit tests don’t generate random data and pepper your application with it in unpredictable sequences.  They’re not something that QA generally executes.
And, finally, unit tests don’t exercise multiple components of your system and how they act.  If you have a console application and you pipe input to it from the command line and test for output, you’re executing an end-to-end system test — not a unit test.
Make no mistake — tests that do these things add value.  They should be part of your general approach to code quality.  They just don’t fall under the heading of unit tests.

Unit Testing Best Practices

1. Arrange, Act, Assert

Let’s now consider another sort of unit test anatomy.  Here, I’m talking about the logical components of a good unit test.  The test that I’ve written has them in their absolute most basic form.  Perhaps not surprisingly, given the title of this section, those components are “arrange, act, assert.”
Lean heavily on the scientific method to understand the real idea here.  Consider your test as a hypothesis and your test run as an experiment.  In this case, we hypothesize that the add method will return 7 with inputs of 4 and 3.
To pull off this experiment, first, we arrange everything we need to run the experiment.  In this case, very little needs to happen.  We simply instantiate a calculator object.  In other, more complex cases, you may need to seed an object with some variable values or call a particular constructor.
With the arranging in place, we act.  In this case, we invoke the add method and capture the result.  The “act” represents the star of the unit testing show.  All of the arranging leads up to it, and everything afterward amounts to retrospection.
Finally, we assert.  The invocation of the Assert class probably gave that one away.  But the assert concept in the unit test represents a general category of action that you cannot omit and have a unit test.  It asserts the hypothesis itself.  Asserting something represents the essence of testing.

2. One Assert Per Test Method

I may catch some flak for this from unit testing veterans of a certain testing philosophy, but so be it.  Not everyone will necessarily agree with this, but I believe you should shoot for one assert per test method.  Each test forms a hypothesis and asserts it.  (The contrarian viewpoint would argue that multiple asserts can represent a single hypothesis).
I won’t go so far as to say that no test should ever contain a number of assertions other than one.  But I will say that your unit test suite should have a test to assert ratio pretty darned near 1.
Unit testing newbies commonly make a mistake of testing all of the things in one test method.  After all, more testing is better, right?  This drives them to want to get the most bang for their buck with each test, asserting lots of stuff.
But, remember, hypothesis, experiment.  Think of reading the output of the test in the test runner.  If you assert 20 things, you still only see a single failure.  How will you know at a glance what went wrong — which of your 20 assertions failed?

3. Avoid Test Interdependence

Each test should handle its own setup and tear down.  The test runner will execute your stuff in whatever order it pleases and, depending on the specific runner you use (advanced topic), it might even execute them in parallel.
You, therefore, cannot count on the test suite or the class that you’re testing to maintain state in between tests.  But that won’t always make itself obvious to you.
If you have two tests, for instance, the test runner may happen to execute them in the same order each time.  Lulled into a false sense of security, you might come to rely on this.  Weeks later, when you add a third test, it upsets this mix and one of your tests starts failing intermittently because of the ordering.
This will confuse and infuriate you.  Avoid this interdependence at all costs.

4. Keep It Short, Sweet, and Visible

I’ve trod this road before as well and felt the pain.  Resist the impulse to abstract test setup (the “arrange”) to other classes, and especially resist the impulse to abstract it into a base class.  I won’t say that you’ll never find this abstraction appropriate (though I’d argue base classes are never appropriate here), but look to avoid it.
The reasoning here is simple.  When a test fails, you want to understand what went wrong.  You thus want a test where all setup logic reveals itself to you at a glance.  If you have logic strewn all over the class or residing in different classes, you’ll have a defect treasure hunt on your hands.  That’s bad enough in prod code, but tests are supposed to help eliminate that.  Make it easy on yourself.

5. Recognize Test Setup Pain as a Smell

For my second to last best practice mention, I’ll get a bit philosophical.  Stick this one in the back of your head, but do not forget it.
When you first teach yourself to write unit tests, you’ll do so on toy codebases like my little calculator.  It’ll take some real world experience and some notches on your belt before you hit this, but you will hit it.  And, when you do, remember my advice.
If you find that the “arrange” part of your unit test becomes cumbersome, stop what you’re doing.  One of the most undercover powerful things about unit tests is that they provide excellent feedback on the design of your code — specifically its modularity.  If you find yourself laboring heavily to get a class and method setup so that you can test it, you have a design problem.
When you create setup heavy tests, you create brittle tests.  Tests carry a maintenance weight, just like production code.  You thus want to avoid unwieldy tests like the plague — they’ll break and make you and everyone else hate them.  So instead of going nuts on the setup, take a critical look at your design.

6. Add Them to the Build

I’ll conclude the post with arguably the most important best practice.  Since you’re early in your unit testing journey, get started on this one immediately when you only have a single test in your codebase.
If your team has a continuous integration build, add your new unit test suite’s execution to the build.  If any tests fail, then the build fails.  No exceptions, no ifs, ands or buts.  Trust me on this one.  If unit test failures don’t stop your team’s progress, your team will eventually start ignoring the failures when the pressure to deliver mounts.  It’s not a question of if, but when.
Unit testing takes time to learn and even more time to master.  Getting to that mastery will seem incredibly onerous at first, but you won’t ever get there if you don’t go all in.  If you’re going to write ’em, make ’em count.
For details click here

Comments

Popular posts from this blog

Recursive query in Laravel

<?php /** * Created by PhpStorm. * User: Zafar Hayat * Date: 6/26/2020 * Time: 7:06 PM */ namespace App\Services; use Illuminate\Support\Facades\DB; class FileWithDeepSearch { /** * @var PHPFunction */ private $PHPFunction ; /** * @var Common */ private $common ; /** * @var Filters */ private $filters ; public function __construct( PHPFunction $PHPFunction , Common $common , Filters $filters ) { $this -> PHPFunction = $PHPFunction ; $this -> common = $common ; $this -> filters = $filters ; } public function getQuery( array $data ) { $currentDirectoryFilesQuery = $this ->getCurrentDirectoryFilesQuery( $data ); $recursiveQuery = $this ->getRecursiveQuery( $data ); $recursiveQuery = $recursiveQuery ->unionAll( $currentDirectoryFilesQuery ); return $recursiveQuery ; } private function getCurrentDire...

How To Update PHP In XAMPP

 downloaded the version of PHP that I wanted (7.1.17) and then I strategically replaced the one I had in XAMPP with it. Here are the steps I followed. Download your desired PHP binary from  here . Make sure you download the same build type as your current version. If you don’t know what this is, go ahead and download an  x86 Thread Safe  version since most XAMPP installations have that build. In my case, I downloaded the 7.1.17 VC14 x86 Thread Safe  build. Extract the contents of the Zip file. Create a backup of your current  xampp/php  folder. I called mine php-backup7.1.2 Still inside /xampp, create a new php folder, then copy the contents of the extracted zip file into it. If you have custom configurations in the php.ini file, copy and replace it from your old php folder to the new one. If you didn’t previoisly edit the your php.ini, then skip this step. In my case I had previously installed drivers for sql server and defined them in my php....

Jmeter

JMeter Advantages Open source license : JMeter is totally free,  allows developer use the source code for the development Friendly GUI : JMeter is extremely easy to use and doesn't take time to get familiar with it Platform independent : JMeter is 100% pure Java desktop application. So it can run on multiple platforms Full multithreading framework . JMeter allows concurrent and simultaneous sampling of different functions by a separate thread group Visualize Test Result:  Test result can be displayed in a different format such as chart, table, tree and log file Easy installation : You just copy and run the *.bat file to run JMeter. No installation needed. Highly Extensible : You can write your own tests. JMeter also supports visualization plugins allow you to extend your testing Multiple testing strategy : JMeter supports many testing strategies such as  Load Testing , Distributed Testing, and  Functional Testing . Simulation : JMeter can simulate mul...