0

I'm learning unit testing and wonder if this Unit test program flow (as in Arrange, Act, Assert) is correct?

[TestFixture]
public class unitTest2
{
    private CoffeeMaker coffemaker;
    [Test]
    public void TestMethod1()       // Testa metoden för kaffe med mjölk. Uppgift 2(b)
    {
        coffemaker = new CoffeeMaker();                        //Arrange
        string res = coffemaker.MakeDrink(new Coffee(true, false));   //Act
        StringAssert.Contains("Coffee with milk", res);            //Assert
    }

}
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
Dan A
  • 107
  • 2
  • 2
  • 7
  • Technically, yes, it is correct. From testing point of view I have a few questions. Does the result, "Coffee with milk", depends on parameters or something input? If you plan more than one test method - I assume you have plan like this - then I would refactor the CoffeeMaker initialization into the initialize method. But, I think this example is oversimplified, especially the testing part. – AndrasCsanyi Apr 19 '15 at 13:18

3 Answers3

0

Looks good, some minor improvements:

[TestFixture]
public class CoffeeMakerUnitTests
{
    [Test]
    public void Test_MakeCoffeeWithMilk_Succeeds()
    {
        // Arrange
        var coffemaker = new CoffeeMaker();

        // Act
        string res = coffemaker.MakeDrink(new Coffee(true, false));

        // Assert
        StringAssert.Contains("Coffee with milk", res);
    }
}

The Arrange/Act/Assert pattern is more visible that way. And you want to avoid anything, that's not local to your test function, because that will only cause trouble once you have a second test function.

Your function should be named "What happens and what is the expected result" because then you can see what fails in your test results. "UnitTest1 failed" is not very descriptive.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
0

Arrange is where you set everything up for your test. Act is where you perform some action on the SUT (System Under Test). Assert is where you verify the outcome of that action.

Does your test fit into this reasoning? Yep.

You should also consider the naming convention that you are using. Here is one that follows MethodName_Scenario_ExpectedResult for test method names:

[TestFixture]
public class CoffeeMakerTests
{
    [Test]
    public void MakeDrink_CoffeeWithMilk_ReturnsCorrectString() // Testa metoden för kaffe med mjölk. Uppgift 2(b)
    {
        // Arrange
        var coffeemaker = new CoffeeMaker();
        var coffeeWithMilk = new Coffee(true, false));

        // Act
        var resultString = coffeemaker.MakeDrink(coffeeWithMilk);

        // Assert
        StringAssert.Contains("Coffee with milk", resultString);
    }
}
transporter_room_3
  • 2,583
  • 4
  • 33
  • 51
0

Do's and Don'ts

DO

Name tests with both their expected outcome and relevant details of the state or input being tested

DON'T

Give tests names that say nothing beyond the name of the method being tested except in trivial cases

Structure Structure tests in three distinct blocks - arrange, act, and assert.

Unit tests tend to have a very regular structure. A common way to refer to this structure is arrange, act, assert: every test must arrange the state of the world to test, act on the class under test by calling methods, and assert that the world is in the expected state afterward.

The arrange block is for setting up details of the external world specific to the situation under test. This involves things like creating local variables that will be reused in the test, and sometimes instantiating the object under test with specific arguments. This step should not involve any calls to the object under test (do that during the act block) or verifications of initial state (do that during assert, maybe in another test). Note that general setup required by all or many tests should be done in the test's setUp method. If your test doesn't depend on any specific external state, you can skip the arrange block.

The act block is where you actually make calls to the class under test to trigger the behavior that is being tested. Frequently this block will be a single method call, but if the behavior you're testing spans several methods then they will each be called here. Simple arguments can be inlined as part of the method call, but more complex argument expressions are sometimes better off extracted to the arrange block to avoid distracting from the intent of the block. The act block may also assign a method's return value to a local variable so that it can be asserted on later.

The assert block is the place to make assertions on the return values collected and to verify any interactions with mock objects. It can also build values required for the assertions and verifications. In very simple tests, the act and assert blocks are sometimes combined by inlining calls on the class under test into an assert statement.

These blocks should be distinct from one another - the test should not perform any additional setup or stubbing once it makes calls to the class under test in the act block, and it should not make further calls to the class under test once verification begins in the assert block.

It should be clear when glancing at the test where each block starts and ends. Usually this can be done by adding a single blank line between each block (though this isn't necessary in simple tests where the blocks are only one or two lines each). In particularly complex tests, especially ones where you have to set up several different objects, you might want to use blank lines within blocks to make them more readable. In this case, one option to distinguish the blocks is to label each with a comment like // Arrange, // Act, and // Assert.

Tests that emphasize this structure are clearer since they make it easy to navigate different parts of the test, and more likely to be complete since the regular structure helps ensure that the details of the behavior being tested aren't hidden or omitted.

Mocking frameworks interact with this structure in different ways. Most modern frameworks like Mockito allow stubs to be configured in the arrange block along with defining local variables, and mocks to be verified in the assert block along with performing assertions. Some older frameworks like EasyMock unfortunately require the expected behaviors of mocks to be specified before invoking the code under test - this requires a fourth "expect" block before the act block which works in a similar way to the assert block.

mavesonzini
  • 341
  • 1
  • 3
  • 9