views:

214

answers:

8

So I'm starting to write a class library of useful methods I've written and picked up over the years, I'll start with two examples of code, then ask my specific questions:

I'd also like to make the argument that this is not a duplicate of some of the other, "where do I start unit testin questions."

Check network connectivity (not internet, just netwok)

    public static Boolean IsNetworkConnected()
    {
        Boolean ret = false;
        try
        {
            String HostName = System.Net.Dns.GetHostName();
            System.Net.IPHostEntry thisHost = System.Net.Dns.GetHostEntry(HostName);
            String thisIpAddr = thisHost.AddressList[0].ToString();

            ret = thisIpAddr != System.Net.IPAddress.Parse("127.0.0.1").ToString();
        }
        catch (Exception)
        {
            return false;
        }
        return ret;
    }

And my IsValiEmail method (note, I didn't write the regex)

   public const String MatchEmailPattern = @"^(([\w-]+\.)+[\w-]+|([a-zA-Z]{1}|[\w-]{2,}))@"
         + @"((([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\."
         + @"([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])\.([0-1]?[0-9]{1,2}|25[0-5]|2[0-4][0-9])){1}|"
         + @"([a-zA-Z]+[\w-]+\.)+[a-zA-Z]{2,4})$";


    public static bool IsValidEmail(string email)
    {
        if (email != null && email != string.Empty) 
            return Regex.IsMatch(email, MatchEmailPattern);
        else 
            return false;
    }

So, my question is how do I test that these methods actually work, obviously I want to start Unit Testing more of my code which is more complex than these quick examples.

I'd like to avoid installing additional tools/frameworks if possible, but I'm open to your ideas.

update

Where should this new Unit-Test code (via the links already posted) live? In the same assembly? A seperate assembly?

+3  A: 

NUnit is probably the unit testing framework that best suits your need. Have a look at their quick start tutorial.

Asaph
+5  A: 

Check out the book. The art of unit testing. The wiki page has a lot of great resources.

J.W.
+1. That's a great starter book.
TrueWill
+1 Agreed, and also a great book once you got the basics but want to get a maintainable test suite.
Mathias
just about anything roy osherove does with unit testing is gold!
Chris Conway
A: 

You can start with Junit, and you can use mocking framework (like mockito) to mock parts of your code that involves using Frameworks. But to use mock framework you need to isolate part of your code that uses external framework into a seperate class or interface and use mock framework to mock the external dependency.

Also in your code you are using a "==" operator for String comparision.


ret = thisIpAddr != System.Net.IPAddress.Parse("127.0.0.1").ToString();

But you should use "equals" method for String comparision .

sateesh
This is a C# question, not a Java question.
TrueWill
OOPS, as you pointed I entirely missed that this isn't a Java question. Thanks for the correction
sateesh
A: 

Agreed with Asaph, NUnit is most widely used framework. That being said, if you do not want to use additional frameworks, VStudio Professional does have unit testing tools built in.
I recommend putting your tests in the same solution, in a separate project, so that you don't have to ship your tests with your assembly.
Your first case is actually not the most obvious to unit test, because your class has an external dependency which will be difficult to replicate: obviously, if the class tests that the machine is connected, the result itself will be dependent on the state of the machine. In other words, if the test fails, you don't know if it is because of your code, or because of something which is outside of the control of your code. These situations are typically approached through Mocking, but that's probably not the easiest thing to start with if you are new to unit testing!
The second case is a much better starting point; essentially you will have to create valid and invalid addresses, and pass them to your method, and check that the result is what it should be.

Mathias
A: 

For the first bit of code you'll want to look into introducing Dependency Inversion so that you can mock out those dependencies and control when the method returns true and when it returns false.

For the second I'd create some NUnit tests that each pass in either valid or invalid emails and verify that the correct result is returned. You do this by either creating one test per email you're wanting to test or creating one test as a row-test (which is possible with NUnit 2.5+).

As for where the tests should live....well they can live in the same assembly or in another assembly... Best practice, at the moment, seems to be to put them in a separate assembly. If you have a project called MyProject you then create a project for your unit tests called MyProject.Tests....and as an added extra it's good to put your integration tests in another assembly called MyProject.Integration.Tests.

mezoid
+2  A: 

You can certainly do unit testing without a framework -- just make an app with a "test" button that runs your tests. However, I've found that it's much nicer to use an existing framework -- They're set up to allow you to easily add tests, see success/failure, and run tests automatically. Nunit is fine, or really, anything will do. MSTest is OK, if you have a version of Visual Studio that comes with it.

IsValidEmail should be easy to test: test with null, "", a valid email, and an invalid email. Then put on a black hat and try sneaking pernicious garbage in: can you make it break? But since this function only operates on its inputs, it is pretty easy to test.

IsNetworkConnected is harder to test. You call GetHostName and GetHostEntry, and you can't control what they return. This makes it hard to check all of the possible modes. Unit testing exerts strong pressure on you to separate your logic from your data retrieval. One option here would be to pass in the IPHostEntry. Of course, this would makes your exception trapping less useful, and push some of it on to the caller.

You could build a function to make the calls to GetHostName and GetHostEntry for you, then pass a delegate to the real one in your app and a fake* one in your test. At some point this strategy costs more than it delivers in value -- You'll have to make that judgment yourself, and don't waste effort on work that doesn't produce value.

*Followers of the Mock Objects technique will note that you should not mock out GetHostName and GetHostEntry, since you do not own them. If you have a mocking framework and wish to use it, feel free; Just don't mistake using their tools with following their design methods.

Sean McMillan
+1  A: 

Testing IsNetworkConnected

Sean McMillan is right in his response that there is not much of a benefit in testing IsNetworkConnected method. It does not encapsulate much logic but only the dependencies which are not worth abstracting. However, let us pretend that it is important to unit test that method due to some reason. The following is the way in which I would go about:

  public static Boolean IsNetworkConnected(IIPAddressProvider ipAddressProvider) 
    { 
        Boolean ret = false; 
        try 
        {
            IPAddress thisIpAddr = ipAddressProvider.GetIPAddressOFLocalHost();
            ret = thisIpAddr.ToString() != System.Net.IPAddress.Parse("127.0.0.1").ToString(); 
        } 
        catch (Exception) 
        { 
            return false; 
        } 
        return ret; 
    }

After doing that I would write the following unit test:

  • Throw exception from the mock of IIPAddressProvider
  • Return Null IPAddress from the mock of IIPAddressProvider
  • Return 127.0.0.1 from the mock of IIPAddressProvider
  • Return different IPAddress other than 127.0.0.1 from the mock of IIPAddressProvider

Testing IsValidEmail

There is a definite value in writing unit tests for this method. You need to try postive, negative and boundary test cases. Also unit testing is form of white box testing. From your method it is clear that you need to exercise on pre-condition of the method and the regular expression while doing unit testing. The important thing here is to exercise the regular expression. There are not many code paths in the method. In my opinion you need to write the above mentioned test case scenarios. Additionally, some third party tools for doing regular expression validation should be used before you use it in your production code.

Where should the test code be located

In my opinion it should always be located in a different assembly from the production code. That is the best choice.

Anand Patel
+1  A: 

Some additional unit testing frameworks can be found here.

dornbraek