1

This is the first time I tried TDD.

At the first time, my controller tests looks like this

use RefreshDatabase;
class ControllerCustomerIndustryTest extends TestCase
{
    use RefreshDatabase;

    public function testIndex()
    {
        // 
    }

    public function testStore()
    {
        // 
    }

    public function testShow()
    {
        // 
    }

    public function testUpdate()
    {
        // 
    }

    public function testDelete()
    {
        //
    }
}

Each test took 4-6 seconds for just this basic functions.

And then I tried changing the structure to reduce the number of RefreshDatabase.

use RefreshDatabase;
class ControllerCustomerIndustryTest extends TestCase
{
    use RefreshDatabase;

    public function testCustomerIndustryController()
    {
        $this->store();
        $this->show();
        $this->update();
        $this->delete();
        $this->index();
    }

    private function index()
    {
        // 
    }

    private function store()
    {
        // 
    }

    private function show()
    {
        // 
    }

    private function update()
    {
        // 
    }

    private function delete()
    {
        //
    }
}

Now each test runs below 1 second, because refreshDatabase only executed once, and I can just copy paste and use the same data for store(), show(), and update(). But then, I'm wondering if this is the right way, or this is actually an antipattern.

Please kindly explain to me what, how, and why test should be?

1

I'm confused. Your class name is ControllerCustomerIndustryTest yet you seem to be testing that you have a database. You should be testing your controller logic. Not it's database connection.

Each test taking 4-6 seconds is unacceptable sure, but getting them all to come in under a second doesn't make up for the fact that you're still not writing a unit test. Not every automated test is a unit test. You can write integration tests but I'd encourage you to master true isolated unit tests before you waste much time and effort on integration testing.

Michael Feathers gives a fairly good outline of things a unit test should not do:

A test is not a unit test if:

  • It talks to the database
  • It communicates across the network
  • It touches the file system
  • It can't run at the same time as any of your other unit tests
  • You have to do special things to your environment (such as editing config files) to run it.

Prefer tests that follow these rules to ones that don't. You should find that they run fast and that few things can't be tested this way.

  • I'm testing the controller with http test, and the controller interacts with database, so I use refreshDatabase trait. So if not using database, how should I test the controller? – Christhofer Natalius Aug 1 '19 at 2:21
0

Please kindly explain to me what, how, and why test should be?

Normally, what happens in a situation like this one is that we change the design of our solution, into two parts

  • One part that knows about the database, but is really simple
  • One part that is complicated, but can run in memory without talking to the database

This is part of the point of "test driven design"; we're including in our requirements the constraint that the code be easy to test. This often takes the form of separating logic (which operates on values in memory) from side effects (reading and writing to the database).

Another way of expressing the idea: we've got two different kinds of tests, those that require side effects like reading from a database, and those tests that can be run purely using information in memory. What we are trying to do is to arrange our code so that all of the complicated logic can be measured by the second kind of test, so that it is faster and cheaper.

See Gary Bernhardt's talk Boundaries for more details on separating the bits that talk to the database (the "shell") from the bits that only need internal memory ("the core").

Mark Seemann's Async Injection talk may also help; but you may have to work harder to see how those ideas fit your question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.