Why?
I've heard this story a million times. Nobody's ever been able to robustly justify it to me. I don't believe it's true.
If you don't have a test for your subsystem that covers the more common use cases; how will you tell if it broke when you updated one of the functions/methods it uses?
If you don't have a test for individual flows at the level of the entire system how will you know when you did something that broke the build outright?
If you do none of that testing; you're handing off that function of your development team to the users of the system you're building.
Testing is an engineering practice that lets you make changes to complex systems with confidence that the system is still doing it's job after the changes you make.
It's not magic; it's engineering. As such, it's aim is to be boringly predictable.
And yeah, it's annoying; but it's a lot less annoying than facing an angry customer who is screaming about lost data, lost money and how they're going to sue you into a smoking hole in the ground for deliberately deceiving them about the issues with your software.
> If you don't have a test for a given item of functionality; how do you know it works?
This would be an integration test
> If you don't have a test for your subsystem that covers the more common use cases; how will you tell if it broke when you updated one of the functions/methods it uses?
That would be a system test
> If you don't have a test for individual flows at the level of the entire system how will you know when you did something that broke the build outright?
I may misunderstand the question, but ... you compile it ?
> Testing is an engineering practice that lets you make changes to complex systems with confidence that the system is still doing it's job after the changes you make.
And if you have unit tests ... doing those changes is twice as hard as when you don't have them. Also if you test the "job" of the complex system, that would definitely not be a unit test.
This is what unit tests look like in large companies. What you actually find in the field
def add1(a):
return a + 1
def TestAdd1(self):
self.assertEquals(add1(2), 3)
self.assertEquals(add1(-2), -1)
self.assertEquals(add1(8), 9)
self.assertEquals(add1(12), 13)
self.assertEquals(add1(5557), 5558)
ThinkNone of your concerns apply to code like this. And nobody, ever, for any reason, should write code like this.
I personally don't get too hung up on whether a given test is a unit test, a system test or an integration test. For any reasonably sized project you're eventually going to have all of those. And sometimes something that was a unit test will suddenly become a test that crosses multiple units as requirements change and as dependencies get added to the project.
The viewpoint I take is that tests are an integral part of the software, they may not be part of the final delivered artifact but they are part of what defines the software.
You should be thinking as much about how to test that your code is doing what it should as to how to make it do so in the first place. If you do that you will have a far better understanding of the intent of any given piece of code and you will have done half the work of debugging before you write the bugs.
self.assertEquals(add1(Integer.MAX_VALUE), ???)