24 ms·
> It's tough to put together a screeencast, much less a series. You have my respect for doing so, and for choosing a simple but non-trivial problem like sorting
by waterlink 11y ago
> It's tough to put together a screeencast, much less a series. You have my respect for doing so, and for choosing a simple but non-trivial problem like sorting that people use every day, instead of something like Fibonacci.
Thanks!
> > I think in this case, I would write new test suite
> I think that's reasonable. I bring this up to point out how the TDD formalism, as red-green-refactor, doesn't work. This means the "refactor" in TDD uses a subset of the available refactoring operations, which further means TDD cannot be the only thing which drives the design.
I believe, that is always the case with any best practice. You hit a point, where the problem you are facing requires something else, or combination of techniques, some analysis and thought. Reminds me about quadrants with "Known", "Knowable", "Complex" and "Chaotic".
> .. TDD is a form of white-box testing ..
I kind of agree on this one. In a lot of cases it is true.
> > I wasn't focusing enough on this point.
> One of my complaints about TDD is that it focuses on tests for the next small code transformation. This is very helpful for a lot of people! But maintaining that focus means that other aspects receive less attention.
And that is exactly my intention: I want to help TDD spreading to the people (at least, the ones I have in reach here, in Berlin), who are not doing testing at all. (or doing it only from time to time). I want to infect them with a concept, and afterwards they will be on their own journey of discovery, what fits their tastes and their problems best; but they will no longer be able to write low-test-covered code. Do you think it is a good idea? Or maybe can be implemented in a better way?
> > And see it fail with stack overflow
> But what if it doesn't fail? Do you leave the test in? Or do you tweak the parameters until if fails? What if a recursive implementation never fails, perhaps because the compiler used tail recursion? How many non-failing tests do you add?
I was playing around with that today. I have actually added (and left in) not only stack-overflow test, but performance test. I was increasing parameters, until reasonable, like 3 * 10 ^ 7 elements, which still can complete in reasonable time for running inside of the test suite.
> Test case analysis is part of the traditional QA process, and I feel that too many TDD people reject it because they see after-the-fact tests as being counter to the TDD philosophy.
I think after-the-fact tests added after you already have decent coverage is a good thing to do, I usually do that, especially in times, when the solution emerged too fast, and you didn't covered some edge cases; how you got to this coverage is a different question, be it a TDD, property-based testing, after-the-fact tests, all-tests-first, and/or anything else. After-the-fact tests help you validate your assumptions about your code you have just written, which allows to spot problems earlier and make code future-proof.
My opinion on TDD philosophy is that it is something that doesn't drive complete design of the thing under implementation (nor it designed to do so, programmers are the ones who should do that), but it does force you to design it in a unit-testable fashion. Which makes adding after-the-fact tests really simple and enjoyable.
- dalke 11y ago"Do you think it is a good idea?" Well, I've tried TDD several times myself, and as part of our local Python User's Group kata. I find it to be a frustrating technique, but I can't deny there are many people who find it useful. I've watched a handful of video walkthroughs of TDD, and gotten frustrated at the lack of good testing or development in them. One example is Robert Martin's primes kata. His solution works, but realistically only for small numbers. He never specified an input domain, and during development never tried to identify ambiguities between the API 'promise' that the function would take int32, the expectation by most that it's fast to factor 2,147,483,647 (2^31-1), and the reality that his code would take a long time for that. You write "I think after-the-fact tests added after you already have decent coverage". I love code coverage as a way to identify missing tests. For me that's usually in error handling. Many of the TDD writings, going back to Kent Beck, say that TDD will naturally lead to high code coverage. I think that's wrong. I again thing many of the TDD writings ignore the problems that can come up during refactoring. I think Martin's TDD style works because the problem he uses are "simple" in an algorithm sense, which is why he can talk about a 'Transformation Priority Premise'. Martin says "Refactorings are simple operations that change the structure of code without changing its behavior", but as I wrote before, 'substitute algorithm' is not a simple operation. Then again, I think most businesses only need simple algorithms, even if the overall goal is quite complex. My complaint is about where TDD isn't enough. So if you also include coverage and after-the-fact tests, that would be far beyond what I've seen so far in TDD walkthroughs. That said, I don't think many people will watch a code walkthrough, so don't expect much fame or uptake from your series. That said, yes, I think it's a good idea. "but it does force you to design it in a unit-testable fashion" You might want to read http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Waste.pdf http://www.rbcs-us.com/documents/Why-Most-Unit-Testing-is-Wa... . There's a follow-up as well. He argues that most time should be spent on integration testing, and I agree. I think unit tests implicitly enforce an API on the code, even when there's no need for an API. It's a special purpose internal API designed for testing. Because they are internal functions, you should have the freedom to refactor them, but the unit test burden keeps you from doing so. (In one TDD kata we did, we got working code, then compared it to others who were there. Our code was several times larger because we had tests for multiple code layers, while they only had one layer. We could have removed the layers, but that would have called for rewriting most of the unit tests, and I think that inhibited our design sense.) In my own code, most of my tests are base on a unit-test framework but I almost only use the public API (for the library code) or a call to main() (for the command-line code). I feel this gives me more freedom to refactor without worrying about the extra work to change the unittests. Anyway, Coplien describes it much better than I, and my comments just now don't even apply to a "sort()" function as that would be a public API.