Hey everyone. With this PR I want to propose a new dedicated Integration test directory and in-memory DB defaults to the default Laravel test suite. As someone who's worked quite a bit with different test suites over the past years I think I can say for myself I have quite some experience in this area and wanted to share some small things through this PR.
The first thing I want to change with this PR is to provide new defaults for the database that's being used when running the test suite of the app. This is probably the very first thing I change for every single app I start working on. All of my tests run in memory against a sqlite database which is pretty fast I must say.
While it is true that the current default Laravel test suite doesn't requires a database to be set up, it is from my understanding that a lot of people do add these new defaults as soon as they need to start testing against a database. It's also true that an sqlite can't mimic a MySQL or Postgres database which is probably used in production but the speed of an in-memory database makes it much more suited for running tests. Therefor, I believe these are good defaults to have in the skeleton.
From what I often read on issues and on Twitter I still see that there's a lot of confusion about what a Unit test is and what an Integration test is. A unit test is something you test in isolation, without booting the entire app. You, for example, test a single object or function without any outside dependencies and maybe mock some of those dependencies. These tests usually run really fast.
Integration tests, however, are tests which test the behavior of different components together. They aren't full cycle tests like End-to-End tests or Feature tests but they do require some additional setup (like a database for example). These tests tend to run a bit slower.
In the current skeleton setup you only have two directories: a Unit test directory and a Feature test directory. I think there's room for an Integration directory which actually copies the behavior of the current Unit test directory. Because you see, the current default Unit ExampleTest extends from the default TestCase. This isn't wanted for unit tests because it boots up the entire framework and thus slows down these tests which should actually run much faster (because they should be isolated).
What I changed is that I've added a dedicated Integration test directory which keeps the current behavior of extending from the Laravel TestCase class and can be used to test different components in your app which require the framework to be booted. The old Unit ExampleTest is updated to only extend the default PHPUnit Testcase so the framework isn't booted and you get the speed boost for these types of test. It's also ok that you don't have all of the Laravel test methods for the Unit tests because most of these methods are meant for Integration tests and provide no value in Unit tests.
I also wanted to make a clear different between what a Unit test and what an Integration test is inside the example tests. For the Unit tests I'm testing if the User model accepts a name attribute and that it can be fetched properly (most people also don't realize you can perfectly Unit test Eloquent models as long as you don't do DB operations). For the Integration test I've added an example which actually makes use of the newly in-memory database defaults and I seed three users and fetch them with the User model.
What I'm mainly trying to achieve with these changes is to educate people better about testing in general and what the different types of tests are. And I'm hoping this saves a lot of people some time when they start on a new Laravel app (even though the changes are minimal).
I'm sorry for writing such a large description. I'm usually against these myself hehe. But I wanted to be thorough enough to explain the reasoning behind it 🙂
Let me know what you think.
Update: Taking from the feedback here I've made changes to this PR. More info here: https://github.com/laravel/laravel/pull/5169#issuecomment-562202777