简体   繁体   中英

Unit testing concept, should these assertions be splitted to be “unit”?

Despite the fact that I'm being playing for a little while with unit testing, I can't really get the concept of "unit", that is a single functionality.

For example, I'm testing a group of magic methods in the form of newXxx :

public function testMagicCreatorWithoutArgument()
{
    $retobj = $this->hobj->newFoo();

    // Test that magic method sets the attribute
    $this->assertObjectHasAttribute('foo', $this->hobj);
    $this->assertInstanceOf(get_class($this->hobj), $this->hobj->foo);

    // Test returned $retobj type
    $this->assertInstanceOf(get_class($this->hobj), $retobj);
    $this->assertNotSame($this->hobj, $retobj);

    // Test parent property in $retobj
    $this->assertSame($this->hobj, $retobj->getParent());
}

As you can see there are three "groups" of assertions in this test method. Should I split them into three single test methods, in order to follow the "unit testing" principle?

Split would be something like:

public function testMagicCreatorWithoutArgumentSetsTheProperty()
{
    $this->hobj->newFoo();

    $this->assertObjectHasAttribute('foo', $this->hobj);
    $this->assertInstanceOf(get_class($this->hobj), $this->hobj->foo);
}

/**
 * @depends testMagicCreatorWithoutArgumentReturnsNewInstance
 */
public function testMagicCreatorWithArgumentSetsParentProperty()
{
    $retobj = $this->hobj->newFoo();

    $this->assertSame($this->hobj, $retobj->getParent());
}

public function testMagicCreatorWithoutArgumentReturnsNewInstance()
{
    $retobj = $this->hobj->newFoo();

    $this->assertInstanceOf(get_class($this->hobj), $retobj);
    $this->assertNotSame($this->hobj, $retobj);
}

Your test method is testing this:

   $retobj = $this->hobj->newFoo();

in one test, and performing multiple assertions on this one object. That doesn't seem unreasonable.

I would be more concerned if you were testing multiple method invocations in the one test. Why ? An early assertion would abort the test and not perform a test on a further method. At best that means the second method wasn't tested, and at worst it hides evidence revealed by the 2nd test (that evidence could help identify the cause or scope of the first failure)

For this reason I do try to avoid too many assertions in the unit test method. It's not unreasonable to check for a null object, and then check (in the same test) for a populated field. I wouldn't chain those assertions together, though, and would rather have multiple tests testing different functionality of the same returned entity.

As ever, there's a degree of practicality to be applied here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM