@AkiyamaSmart I would not worry too much about the terminology - it will drive you mad! I used to get caught up into what type of tests I am writing, and realised I spent more time worrying about writing my test to fit within textbook definitions than developing the actual systems the tests were supposed to help build. Now I realise that the lines between each type of tests are blurred when doing real development unlike in contrived simplistic tutorials.
What I find more helpful to understand is the different approaches to testing that you can follow. By this I mean:
"Strategic" level: Test-First (TDD) or Test-Last (Regression Tests)
Most of the tutorials within the Laravel (indeed the PHP) community are about writing tests after writing the code. Whilst there is benefit to this when it comes to changing your code later (by way of writing a regression suite you can use for refactoring / future changes), you miss out on the main strength of writing tests, which is TDD. With TDD you write your tests first then write the code to make the tests pass. Benefits include:
- Discovering your emergent design as you write the tests. You start with a goal and not (normally) an implementation, then write the tests to design the way towards your goal and then write the code to pass the tests. The level of abstraction here means you do not get caught up in thinking about the implementation details.
- Removing yourself a level from the code to think about the system from a behavioural point of view.
- Slowing down the coding process, to help give yourself time to think and not just churn out rubbish code.
- Seemingly contradictory to the last point; speeding up the development process. With TDD you need to keep less of the system context in your head at once. This allows you to focus on the piece of code you are implementing, in the knowledge that the rest of the code that has come before it works as required, and the code you are writing now should not break it (and if it does, you have the tests in place to easily fix it!)
- Greater test coverage; you tend to think of the edge-cases a lot sooner and often write tests for the sad path, whereas writing test-last will tend to focus on the obvious, which is the happy path only.
- Refactoring is simple and true to the needs of the design. If you write your tests after the code, then what guarantees do you have that you have written the right test for your code? It doesn't take long to forget what the code you have written does! If your Test-Last test passes, but it is not testing everything, then you have some unaccounted for edge-cases (potential bugs). With TDD you will tend to test more of these edge-cases as you develop your design, therefore you have more coverage.
I'm sure if I had the time, I could give you another list of 4-5 big reasons why TDD is far superior to Test-Last.
"Tactical" level: Outside-In & Inside-Out
As opposed to thinking about integration tests, unit tests, functional tests, acceptance tests, end-to-end tests etc. try to think of the pattern of your test running through the different layers of the system (like layers of an onion).
You can start in the middle with a "unit" test and then jump out of the layers to write tests for code that hits more dependencies, or you can start on the outside to write a test that touches everything (aka integration test / acceptance test / end-to-end test - with 3 overlapping types, you can see why I don't bother naming them too much!) and drops you deeper into the system to write the more specific tests and implementation codes. You can then drop in and jump out to the levels you need to make the tests pass.
In all, think about the flow of the tests and what dependencies they hit, and it will all come together well and don't get hanged up about the names of the types of tests you are writing...