Philosoraptor meme explained... Just think (twice 😅) about it.
Why I am writing this article? Because twitter might be not the best place to explain the problem.
What is the problem? Well, problem is quite well defined at Twitter, as an reply to Dan Abramov post.
Tim@timneutkens@dan_abramov In the Next.js codebase nearly everything is integration tests, this means we could completely swap out eg the Link implementation and be confident that it still works like it did before.
Even more importantly we test HMR and production mode like that too.22:44 PM - 18 Jul 2019
And everybody instantly might think about another tweet:
And yeah - about that famous article I was asked to read so many times - Write tests. Not too many. Mostly integration by Kent C. Dodds.
So - why I am writing this article? Because people often don't read articles properly - only clickbait captions. And I asked to think. So...
I reckon - about "cohesion", the same stuff we like
components for, along with
CSS-in-JS and other stuff - easy to build together, easy to change together, easy to delete together.
And cohesion between
tests for that stuff could only be achieved if only tests are "unit", and not testing anything else except their stuff. It's like a definition of the unit testing.
Obviously - if you test your stuff in isolation, that would end... well
It like React 15->16 upgrade, when React completely changes inside, but not outside.
Better think about what React should test... React should test React, let you code keep working. No matter of internal React changes
🙀 With today’s release of React 16, we’ve completely rewritten the internals of React while keeping the public API essentially unchanged.🙀
Well - about the danger of testing things in the isolation. Let me quote the right moment from the original article - you are testing "umbrella open", and "umbrella", well, would "open". All tests are green, all pieces are working ideally!!! What's your problem, mate??
That's absolutely true. That's how it should work. If you forgot the main idea - protect someone from the rain, that is the main, and the only reason for umbrella to exists. And the rest are implementation details.
Should you use "integration tests" here? Well - it probably would help, but there are so many "properly working" umbrellas, which are not
"properly" protecting you from the rain.
First of all - integration tests are not a simple thing. Integration tests are doing two different jobs.
- Firstly - integration tests are checking are you doing the right thing. For example calling other things in the right order and in the right way.
- Secondly - they are checking that
thingsare ok if they are called with provided arguments, and acts as expected. Checks that things are doing what they are expected to do.
So is it a good idea to prefer integration tests? What shall you go with unit tests?
Let me explain it a bit differently.
I've started coding, well, about 30 years ago. And, to be honest, tests were not something I was doing all this time. Someone even said that test were not a thing in "pre agile" era - only manual testing, logging, and monitoring. I am from that Era - the Era when we don't "need" tests.
How we were testing stuff before going to prod? Well - we were using the stuff we build, we were consuming the very result.
And it seems to me, what my code was free from any bugs (it is actually still working on production), until I started writing tests. Really - just after I created my first test - my beautiful code become buggy.
Coincidence? Not sure 😅.
I've made so many different things - I just had time for it. I've tried so much - I just had time for it. And I haven't wrote many tests - well, due to three reasons.
- reason 1 - everything was working. Test would be just a waste of my time.
- reason 2 - I had no idea what and why to test. So writing tests would waste even more time.
- reason 3 - I wanted to be free to change whatever I wanted, whenever I wanted. So, I didn't want to waste time :) And, of course, I want to be very very creative.
Sounds familiar? Yeah. So - what then?
- (FYI)I had, and still have stuff in production, which does not covered by a single test. It's working like a clock for years.
- (🤷♂️) I'm doing stupidest mistakes every day.
- (😎) But everything is working.
My experience is telling me one simple thing:
- you need E2E test to understand how "thing" would work for a customer, which would communicate with your app via human-machine interfaces (a mouse). Is your application doing the right thing - that’s the main, everything else is an implementation detail.
- you need Integration tests to understand how "things" are working together (wiring). How molecules and blocks are connected. How some Isolated Domains Behave.
- you need Unit tests to understand how "things" working internally. How your code is really working. Sometimes that’s an easy task, and it’s really hard to make a mistake or code something you was not going to. But sometimes - oh dear 🤦♂️.
Even a few lines of code, you just wrote, and you are "absolutely confident in" - might work not as you are thinking.
If you read this proposition more carefully - they form a pyramid. Not that "testing pyramid", but just a pyramid - every level test one level below it, but not anything else. And all tests are the same.
Anton Korzunov@thekasheyThere is a function - it has input and output - and you may assert that your requirements are met without unwrapping internals.
Then step forward and test those internals in a same way. One step per time. From the top to the bottom, and back:
dev.to/thekashey/pref…06:41 AM - 11 Aug 2019
So - once you secured the right application behaviour by E2E tests - then feel free to do one level down and check how it’s really works.
- E2E tests precede integrations - they define the "flow" or your app, and that's the main.
- integration precede unit testsm as long as they might affect design requirement, and thus architecture decisions for the lower levels. Like YAGNY, but for application building blocks.
- unit tests also might precede something (by induction!), but what?
Every upper lever precede lower level. level > level + 1
This "testing pyramid" is working well when we are building something from top to the bottom, but but more often we are starting building lower-level blocks first, or replacing one low-level block by another - here existing
restrictions from upper layers would be a guidance for you. If that upper level exists.
In short - write README before the code. Or specifications.
But not tests!
You have to have restrictions or requirements beforehand.
And the idea of this article is quite simple - there are no such things like integration tests or unit tests.
There are tests, and there are requirements. And that's the only difference.
Tests are working for the current layer, and requirements are responsible for the something next to them - they are providing expectations for the next step.
You might change the actual code implementation, and code requirements should still be ok, if they are met.
With today’s release of React 16, we’ve completely rewritten the internals of React while keeping the public API essentially unchanged.
Changing code should always break tests, if something real is changed in real.
So the real question is "do you need tests", not "requirements". While integration/unit separation does not make any sense.
You know - requirements is everything you, and your code, should met from the business point of view. And from the customer point of view. Please keep every else point for yourself.
PS: And TDD(Testing Driven Development) is RDD(Requirement Driven Development) in real - first you shall define "requirements", then "met" them.
You have to separate these two concepts in your mind - "what" you are testing, not "how" you are testing.
Actually "Requirement Based Testing" is a thing, and there is another Dev Article about it -
Requirements-based testing is a testing approach in which test cases, conditions and data are derived from requirements. It includes functional tests and also non-functional attributes such as performance, reliability or usability.
Every time you are using
react-testing-library, which encourage good testing practices, and helping you not to test internals - you are doing "requirement based" testing, not just "integration", and it's still important to distinguish top level requirements from from lower level requirements, which are implementation details.
There are more abstract requirements, and more concrete requirements and nuances - together they form the Real Testing Pyramid.
As I said - just think twice.
Integationraptor meme explained?