views:

215

answers:

3

I'm very new to TDD and I'm having trouble with one of my unit tests. I just can't seem to understand what to do next. :( I'm trying to unit test a service of mine called AccountService and I'm testing a method called DoLogin(username, password). Here's some example code:

    [Test]
    public void User_With_Correct_Username_And_Pass_Should_Login_Successfully()
    {
        // Arrange
        var accountService = new AccountService();

        // Act
        bool result = accountService.DoLogin("test", "test");

        // Assert
        Assert.IsTrue(result);
    }

    public class AccountService : IAccountService
    {
      public bool DoLogin(string username, string password)
      {
        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))
            return false;

        return true;
      }
    }

So this test pasts but now what do I do?! How do I really test if a valid login occured? Do I need to implement an integration test and test the login against a real or in-memory DB? Sorry if I'm doing things totally incorrect. I really hope one day to get this TDD stuff down. Thanks

A: 

You should have a test that an invalid username or invalid password causes DoLogin() to fail.

Given the name of the function, (DoLogin() rather then CheckLogin()) I'd think the function should have some side effect as well. The test should verify that side affect. Really need to clarify what that is before someone can clarify how it should be verified.

Frank Schwieterman
+1  A: 

Pass what you know to be valid and invalid credentials to DoLogin, and then compare the results to what you expect. Try to imagine every possible (read: reasonable) combination/input of the "username" and "password" parameters the user will provide, and create a test for each.

If your DoLogin business logic is to be believed, we're defining a "valid" username (and a "valid" password) to be anything that's populated. Fair enough, for discussion's sake.

Some simple tests come to mind:

Login_With_Null_UserName_Fails()
Login_With_Populated_UserName_Succeeds()
Login_With_Empty_UserName_Fails()
Login_With_Null_Password_Fails()
Login_With_Populated_Password_Succeeds()
Login_With_Empty_Password_Fails()

Or, consider combinations:

Login_With_Null_UserName_And_Populated_Password_Fails()
Login_With_Populated_UserName_And_Populated_Password_Succeeds()
Login_With_Empty_UserName_And_Null_Password_Fails()
etc
etc
lance
Cool, thanks. So after I'm done exhausting my test list for DoLogin what is my next step? Do I then really test the login against a DB?
CalebHC
If you think there's sufficient risk in your sending parameters to and getting the correct results back from your stored procedures, sure!Testing helps lower risk and improve code. I recommend tests anywhere you reasonably anticipate either opportunity.
lance
+3  A: 
Josh
Thank you so much for taking time to write this! I really appreciate it. You said lots of good stuff and it will probably take me awhile to grasp everything. You're right that I have to get used thinking differently when doing TDD. Hopefully my confusion some day will pass, but that will just take time. Thanks again!
CalebHC
It took a long time before I had that "Ah Ha" moment, but now I am totally converted. I would encourage you to check out another SO post I made about TDD: http://stackoverflow.com/questions/106800/unit-testing-guidelines/106813#106813
Josh