Homam
Homam

Reputation: 23841

Am I using Unit Testing correctly?

This is the first time that I write a TestMethod. Am I using Unit Testing correctly ?

[TestMethod]
public void TestUpdateAccount()
{
    GwIntegrationServiceSoapClient client = new GwIntegrationServiceSoapClient();

    int id = 21; // Target account to update.
    Account accountToUpdate = client.ReadAccount(id);

    string oldName = accountToUpdate.Name;
    string oldEmail = accountToUpdate.Email;
    string newName = Guid.NewGuid().ToString();
    string newEmail = Guid.NewGuid().ToString() + "@nomail.com";

    // Update the name only, even a value is passed in newEmail 
    // But in the propertiesToUpdate parameter (last one) only Name value is passed.
    // Note: the UpdateAccountProperty could be: 
    //          [UpdateAccountProperty.Name | UpdateAccountProperty.Name.Email]
    client.UpdateAccount(id, newName, newEmail, null, false, UpdateAccountProperty.Name);

    // Read the record after updating from database
    Account updatedAccountFirstTime = client.ReadAccount(21);

    // The name should be changed
    Assert.AreEqual(newName, updatedAccountFirstTime.Name);

    // The email should not be changed
    Assert.AreNotEqual(newEmail, updatedAccountFirstTime.Email);

    ////////////////////////////////////////////////////////////
    // Now, after updating the name and everything is working well
    // Returning the old name to the record.
    client.UpdateAccount(id, oldName, oldEmail, null, false, UpdateAccountProperty.Name);

    // Read the record after updating
    Account updatedAccountSecondTime = client.ReadAccount(21);

    Assert.AreEqual(oldName, updatedAccountSecondTime.Name);
}

Thank you very much for the answers. I've updated my test method to these two methods:

[TestMethod]
public void UpdateAccount_OneValueExpectedToBeUpdated_Updated()
{
    GwIntegrationServiceSoapClient client = new GwIntegrationServiceSoapClient();

    int id = 21; // Target account to update.
    Account accountToUpdate = client.ReadAccount(id);

    string oldName = accountToUpdate.Name;
    string oldEmail = accountToUpdate.Email;
    string newName = Guid.NewGuid().ToString();

    // Update the name only because it's passed by propertiesToUpdate parameter (last one).
    client.UpdateAccount(id, newName, null, null, false, UpdateAccountProperty.Name);

    // Read the record after updating from database
    Account updatedAccountFirstTime = client.ReadAccount(id);

    // The name should be changed
    Assert.AreEqual(newName, updatedAccountFirstTime.Name);
}

[TestMethod]
public void UpdateAccount_NoValueExpectedToBeUpdated_NotUpdated()
{
    GwIntegrationServiceSoapClient client = new GwIntegrationServiceSoapClient();

    int id = 21; // Target account to update.
    Account accountToUpdate = client.ReadAccount(id);

    string oldName = accountToUpdate.Name;
    string oldEmail = accountToUpdate.Email;
    string newName = Guid.NewGuid().ToString();
    string newEmail = Guid.NewGuid().ToString() + "@nomail.com";

    // Update the name only, even a value is passed in newEmail 
    // But in the propertiesToUpdate parameter (last one) only Name value is passed.
    client.UpdateAccount(id, newName, newEmail, null, false, UpdateAccountProperty.Name);

    // Read the record after updating from database
    Account updatedAccountFirstTime = client.ReadAccount(id);

    // The email should not be changed
    Assert.AreNotEqual(newEmail, updatedAccountFirstTime.Email);
}

Upvotes: 1

Views: 250

Answers (4)

Paul Turner
Paul Turner

Reputation: 39625

This is difficult to answer, because the kinds of tests you will find under the title of "Unit Testing" will vary. Mostly, "Unit Test" is used as a synonym for "Automated Code Test", which strictly speaking, is anything which tests code in some automatic fashion by writing code.

If you want to write good unit tests, there are only a few rules to follow:

  • Test scenarios independently.
  • Test objects independently.
  • Keep your tests small and focused. If they bloat, create methods to help reduce the boilerplate code and focus on the specifics of the test.

Ultimately, test one thing per test. That way when one particular behaviour or scenario breaks, you have an immediate focus as to which specific part of an object has failed. In your example, you seem to be testing a number of things in a single method, if the first call to UpdateAccount succeeds, but the second one fails, the whole test fails and you aren't clear as to which part of the object has failed.

Upvotes: 5

Jackson Pope
Jackson Pope

Reputation: 14640

Some people (including Roy Osherove in his The Art of Unit Testing) recommend one assert per unit test, seeing as if the first assert fails an exception is thrown and none of the remaining code is called and no other asserts are checked.

This could be split into two or more unit tests to achieve this, e.g. one for checking the name after update, one for checking the email address and potentially one to check that changing and changing back works.

Upvotes: 1

Oliver
Oliver

Reputation: 45101

You should get a copy of The art of unit testing.

Some points to be mentioned:

  • Only one Assert per test.
  • Naming conventions for test method: public void MethodUnderTest_Scenario_Behavior()

Upvotes: 3

graham.reeds
graham.reeds

Reputation: 16476

It seems good. I generally have less lines in my tests.

Could some of the boilerplate be moved into a fixture?

Upvotes: 1

Related Questions