Comments by "" (@grokitall) on "Unit Testing Is The BARE MINIMUM" video.
-
2
-
1
-
You call them requirements, which generally implies big upfront design, but if you call them specifications it makes things clearer.
Tdd has three phases.
In the first phase, you write a simple and fast test to document the specifications of the next bit of code you are going to write. Because you know what that is you should understand the specification well enough to write a test that is going to fail, and then it fails. This gives you an executable specification of that piece of code. If it doesn't fail you fix the test.
Then you write just enough code to meet the specification, and it passes, proving the test good because it works as expected and the code good because it meets the specification. If it still fails you fix the code.
Finally you refactor the code, reducing technical debt, and proving that the test you wrote is testing the API, not an implementation detail. If the valid refactoring breaks the test you fix the test, and keep fixing it until you get it right.
At any point you can spot another test, make a note of it, and carry on, and when you have completed the cycle you can pick another test from your notes, or write a different one. In this way you grow your specification with your code, and is it incrementally to feed back into the higher level design of your code.
Nothing stops you from using A.I. tools to produce higher level documentation from your code to give hints at the direction your design is going in.
This is the value of test first, and even more so of tdd. It encourages the creation of an executable specification of the entirety of your covered codebase, which you can then throw out and reimplement if you wish. Because test after, or worse, does not produce this implementation independent executable specification it is inherently weaker.
The biggest win from tdd is that people doing classical tdd well do not generally write any new legacy code, which is not something you can generally say about those who don't practice it.
If you are generally doing any form of incremental development, you should have a good idea as to the specifications of the next bits of code you want to add. If you don't you have much bigger problems than testing. This is different from knowing all of the requirements for the entire system upfront, you just need to know enough to do the next bit.
As to the issue of multi threading and micro services, don't do it until you have to and then do just enough. Anything else multiplies the problems massively before you need to.
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
@ContinuousDelivery this is exactly the correct analogy to use.
In science what you are doing is crowd sourcing the tests based upon existing theories and data, and using the results to create new tests, data and theories.
Peer review is then equivalent of running the same test suite on different machines with different operating systems and library versions to see what breaks due to unspecified assumptions and sensitivity to initial conditions.
This then demonstrates that the testing is robust, and any new data can be fed back into improving the theory.
And like with science, the goal is falsifiability of the initial assumptions.
Of course the other problem is that there is a big difference between writing code and explaining it, and people are crap at explaining things they are perfectly good at doing. Testing is just explaining it with tests, and the worst code to learn the skill on is legacy code with no tests.
So people come along and try to fit tests to legacy code only to find that the tests can only be implemented as flaky and fragile tests due to the code under test not being designed for testability, which just convinces them that testing is not worth it.
What they actually need is to take some tdd project which evolved as bugs we're found, delete the tests, and compare how many and what types of bugs they find as they step through the commit history. If someone was being really nasty they could delete the code, and reimplement it with a bug for every test until they got code with zero passes, and then see what percentage of bugs they found when they implemented their own test suite.
1
-
Tdd comes with a number of costs and benefits, and so does not doing tdd or continuous integration.
The cost of doing tdd is that you move your regression tests to the front of the process, and refactor as you go and it can cost up to 35 percent extra in time to market..
What you get back is an executable specification anyone can run to reimplement the code in the form of tests, a set of code designed to be testable with very few bugs, and the combination is optimized for doing continuous integration. You also spend very little time on bug hunting. it also helps with areas that are heavily regulated as you can demonstrate on an ongoing basis that it meets the regulations.
All of this helps with getting customers to come back for support, and for repeat business.
Not doing tdd also comes with benefits and costs.
The benefit Is mainly that your initial code dump comes fast, giving a fast time to market.
The costs are significant. As you are not doing incremental testing, the code tends to be hard to test and modify. It also tends to be riddled with bugs which take a long time to find and fix. Due to the problem of being hard to modify, it is also hard to extend, and if they have to get someone else to fix it it can sometimes be quicker to just reimplement the whole thing from scratch.
This tends to work against getting support work and repeat business.
As for the snowflake code no one will touch, it will eventually break, at which point you end up having to do the same work anyway, but on an emergency basis with all the costs that implies. Testing is like planting a tree, the best time to do it is a number of years ago, the second best time is now.
The evidence for incremental development with testing is in, in the dora reports. Not testing is a disaster. Test after gives some advantages initially, while costing more, but rapidly plataus. Test first cost a very little more than comprehensive test after, but as more code I covered you get an ever accelerating speed of improvements and ease of implementation of those improvements, and it is very easy for others to come along and maintain and expand the code, assuming they don't ask you to do the maintenance and extensions.
1
-
1
-
@nschoem that perception definitely exists, and is based upon intuitive feelings that writing tests with your code takes longer, which is true but not really relevant. What happens with feature addicted managers is that they start off saying get the feature to work and we can write the tests later. Then they prioritize the next feature over testing, resulting in no tests, and what few tests do get written are fragile because the only way to test most code that was not designed with tests in mind tend to rely on implementation details to work at all.
This results in code with increasing levels of technical debt which gets harder and harder to debug and extend, making everything slower. The only way to fix this is by refactoring your way out of the problem, which needs tests, and test after tests are harder to write and fragile, so you end up writing tdd style tests for the refactored code so you can just delete those original tests as they cease being helpful.
You still have to write the tests in either case if you have a long lived or large code base, but tdd style tests first tests tend to be API tests which don't depend on internal implementation details, and thus don't break much.
1
-
@lucashowell7653 the tests in tdd are unit tests and integration tests that assert that the code does what it did the last time the test was run. These are called regression tests, but unless they have high coverage and are run automatically with every commit you have large areas of code where you don't know when something broke.
If the code was written before the tests, especially if the author isn't good at testing, it is hard to retrofit regression tests, and to the extent you succeed they tend to be flakier and more fragile. This is why it is better to write them first.
Assuming that the code was written by someone who understands how to write testable code, you could use A.I. to create tests automatically, but then you probably would not have tests where you could understand easily what the test failing meant due to poor naming. When you get as far as doing continuous integration the problem is even worse, as the point of the tests is to prove that the code still does what the programmer understood was needed and document this, but software cannot understand this yet. If you go on to continuous delivery, you have additional acceptance tests whose purpose is prove that the programmer has the same understanding of what is needed as the customer, which requires an even higher level of understanding of the problem space, and software just does not understand either the customer or the programmer that well either now or in the near future.
This means that to do the job well, the tests need to be written by humans to be easily understood, and the time which makes this easiest is to write one test, followed by the code to pass the test. For acceptance tests the easiest time is as soon as the code is ready for the customer to test, adding tests where the current version does not match customer needs. Remember customers don't even know what they need over 60% of the time.
1
-
@temper8281 this is the argument I've heard from everyone who can't write good tests, as well as from those who don't understand why testing matters. If you are just doing a little hobby project which nobody else is ever going to use, and is never going to be extended, then you can mostly get away with not having tests.
As the project gets bigger, or more popular, or has more developers you need the tests to stop regressions, communicate between developers, spot coupling, and numerous other things, most notably to deal with technical debt. The more any of those factors rise, the higher the cost of shipping broken code, and thus the more the tests matter. By the time you need continuous integration you cannot do without the tests, but the harder it is to retrofit them to your existing legacy code base, so it is better to learn how to do testing earlier and add it to the project sooner.
1
-
1
-
1
-
1
-
1
-
1
-
@deanschulze3129 there are reasons behind the answers to some of your questions, and I will try and address them here.
First, the reason tdd followers take automated regression testing seriously is that a lot of the early advocates came from experience with large teams writing complex software which needed long development times. in that context, regression tests are not optional, as lots of people are making lots of changes to different parts of the code that they don't know very well.
This led to the development of continuous integration, where code coverage for regression testing was essential.
Tdd later came along after the development of continuous integration, with the added awareness of technical debt to add refactoring to the continuous integration cycle.
You don't seem to understand just how recent the understanding of how to do regression testing is. Even the idea of what a unit test is was not present in the 2012 version of the book "the art of software testing", but it forms the base of the testing pyramid at the heart of regression testing.
Also, automated regression testing cannot work unless you get management buy in to the idea that code needs tests, and broken tests are the most important code to fix, which is even harder to get quickly, but all of the tech giants do exactly that. You cannot do continuous integration without it.
Even worse, you cannot learn good test practices trying to fit tests to code written without being tested in mind. The resulting tests tend to have to depend on implementation details and are often flakey and fragile, further pushing against the adoption of regression testing.
As to statistics, the dora metrics produced from the annual state of Dev ops report clearly indicated that no testing produces the worst results, test after initially provides better results than no testing, but only up to a certain point due to the previously mentioned problems with retrofitting regression tests to code not designed for it, and test first produces ever faster production of code of higher quality than either of the other two.
The methodology surrounding the report is given in detail in the accelerate book, by the authors of the state of Dev ops report as they got fed up of having to explain in detail to every new reader they encountered.
Bear in mind, the number of programmers doubles every five years, so by definition most programmers have less than five years experience in any software development methodology, let alone advanced techniques. Those techniques are often not covered in training courses for new programmers, and sometimes are not even well covered in all degree level courses.
1