127

Recently, a person here asked a basic question about how to compute in Python all permutations of elements from a list. As for most questions asked by students, I haven't provided the actual source code in my answer, but rather explained how to approach the problem, which essentially ended up in a basic presentation of test driven development.

Thinking about the problem itself, I remembered all the similar problems I did have to solve when I was myself studying programming in university. We were never taught about test driven development, nor any comparable method, but nevertheless were constantly asked to write algorithms which sort elements from a list, or solve Towers of Hanoi puzzle, etc. Nor do all the students who come on SoftwareEngineering.SE seem to know how TDD (Test Driven Development) would help them solving the problems they are given: if they were, they would have formulated their questions very differently.

The fact is, without TDD, all those problems are indeed quite challenging. I consider myself a professional developer, but I would still spend some time writing a list-ordering algorithm without TDD, if asked, and I would be mostly clueless if I were asked to compute all the permutations of the elements in a list, still without using TDD. With TDD, on the other hand, I solved the permutations problem in a matter of minutes when writing the answer to the student.

What is the reason TDD is either not taught at all or at least very late in universities? In other words, would it be problematic to explain the TDD approach before asking students to write list sorting algorithms and similar stuff?


Following the remarks in two of the questions:

In your question, you appear to present TDD as a "problem solving device" [...] In the past, TDD has been presented as a "solution discovery mechanism," but even Bob Martin (the principal advocate of TDD) concedes that you must bring a significant amount of prior knowledge to the technique.

and especially:

I'm curious why you think TDD makes a tricky algorithm problem with a well-defined spec easier.

I find it necessary to explain a bit more what is, in my opinion, so magical about TDD when it comes to solving problems.

In high school and in the university, I didn't have any specific techniques to solve problems, and this applied to both programming and mathematics. In retrospective, I suppose that one of such techniques is to review the current/last lesson/lecture and seek relation with the exercice. If the lesson is about integrals, there are chances the problem the teacher asked to solve requires to use integrals. If the lecture was about recursion, there are chances that the puzzle given to the students could be solved using recursion. I'm also sure there are well formalized approaches to solving problems in mathematics, and those approaches can be applied to programming as well; however, I never learned any.

This means that in practice, my approach was simply to poke the problem around, trying to guess how should it be solved. Back then, if I was given the challenge of generating permutations of elements from a list, I wouldn't start with an empty list as input, but rather an illustrative example, such as [4, 9, 2], trying to figure out why are there six possible permutations, and how can I generate them through code. From there, I need a lot of thinking to find a possible way to solve the problem. This is essentially what the author in the original question did, ending up using random. Similarly, when I was a student, no other students of my age would start with []: all would immediately rush to the case with two or three elements, and then remain stuck for half an hour, sometimes ending up with code which doesn't compile or doesn't run.

The TDD approach, for me, appears to be counter-intuitive. I mean, it works very well, but I would have never figured out myself, before reading a few articles about TDD, that (1) I should start with the simplest case, (2) write the test before writing code, and (3) never rush, trying to fulfil several scenarios in code. Looking at how beginner programmers think, I have an impression that I'm not the only one finding it counter-intuitive. It may be, I believe, more intuitive for programmers who have a good understanding of a functional language. I suppose that in Haskell, for example, it would be natural to handle the permutations problem by considering first a case of an empty list, then a case of a list with one element, and then a case of a list of multiple elements. In languages where recursive algorithms are possible, but not as natural as in Haskell, such approach is however much less natural, unless, of course, one practices TDD.

Thomas Owens
  • 79,623
  • 18
  • 192
  • 283
Arseni Mourzenko
  • 134,780
  • 31
  • 343
  • 513
  • 13
    I believe, this question is on-topic on both sites, and given the different audiences may generate interesting answers on both. There are some related questions already: https://cseducators.stackexchange.com/q/961/945, https://cseducators.stackexchange.com/q/908/945, https://cseducators.stackexchange.com/q/872/945 . – Jörg W Mittag Dec 31 '19 at 22:42
  • 14
    Either I am entirely misunderstanding what you mean by TDD, or there is a problem with your examples, because they are... well, I suppose unitary would be the word. Either you understand the problem, and can write code that works, or you don't. There are really no intermediate steps or sub-modules that you can test. – jamesqf Jan 01 '20 at 18:05
  • 8
    Are you very confident in this question that you mean "TDD" rather than "making a list of expected inputs and outputs"? – Dewi Morgan Jan 02 '20 at 00:45
  • 2
    I'm not sure how TDD would have resulted in you solving your school problem differently. You described starting by immediately rushing to a particular case. That's what most beginner students do. Specifically, they write code that works on the test cases that the book shows or the question specifies. So, with TDD, you'd likely have done the same and not gained much, other than automating your testing of those test cases. TDD only has utility once you've learned enough to realize that as a human, you will fall into those patterns over and over again, regardless of how well you understand ... – iheanyi Jan 02 '20 at 15:35
  • 1
    algorithms or a given problem and absent something external that forces you to consider the universe of possible inputs and outputs and necessarily tests those, you will forget or leave our or overlook some case that will break your code somewhere down the line. TDD imposes discipline to writing code but an experienced programmers process should not have been that different prior to using TDD. TDD just makes it more explicit and shifts the emphasis to considering not only the behavior you want, but behaviors you don't want. – iheanyi Jan 02 '20 at 15:37
  • 1
    Not a complete answer, but -- universities teach theory, not practice. TDD has nothing to do with computer science theory, and everything to do with the practical matters of humans writing code. I don't really enjoy the nearly complete focus universities have on pure academia and matching lack of actually preparing people for the workplace, but it exists nonetheless. – Matthew Read Jan 02 '20 at 17:20
  • 1
    @MatthewRead the university where I was taught CS had a mix of practical vs theoretical subjects. In particular, it had more than one subject related to Software Engineering. It seems TDD would neatly fit as a "current practice" in a SE subject... – Andres F. Jan 02 '20 at 17:30
  • 18
    If I had to make a list of "vital concepts that CS students aren't taught, but should be", version control would be at #1, and TDD would be very far down. – Ian Kemp Jan 02 '20 at 20:38
  • 6
    The problematic assumption is the fact that TDD is good and has no negatives. It's also not the only *solution discover mechanism* out there. There are many other mechanism (I prefer top-down programming) since I think unit tests are counterproductive in many programs, especially in frontend applications. – Sulthan Jan 02 '20 at 22:41
  • @Ian Kemp: I don't know about all universities, but long, long ago when I was an undergrad, we learned about something called RCS. The problem is that new "improved" version control systems - SCS, CVS, Subversion, Mecurial, GIT - come along faster than I can keep track of them. IIRC I worked on one project that used three different ones at different times. – jamesqf Jan 03 '20 at 05:06
  • 3
    How long ago did you study at University? My son's first intro programming class as Software Engineering student at Iowa State used TDD from the very start. – John Hascall Jan 03 '20 at 06:21
  • 2
    Where do you live? Here in the Netherlands, TDD has been hammered into our heads. – Hugo Jan 03 '20 at 13:09
  • 3
    I wasn't taught "TDD" in university, but most programming classes I took the instructors provided harnesses for the programming assignments which amounted to a very similar thing. The harnesses were essentially a suite of unit tests. – Mr.Mindor Jan 03 '20 at 15:52
  • 6
    In roughly 25 years and a dozen software-development positions, I have *never* seen TDD actually implemented in a company... I've seen a few attempts, which had been so cripplingly slow that the devs have threatened to quit over it. Perhaps it's related to my sector, or team size, or company size, or company culture... but almost everyone settles for "testable, somewhat/ mostly tested" code vs. a TDD cycle. YMMV – Jeremy Holovacs Jan 03 '20 at 21:10
  • 1
    Vote to close, much too broad, and not entirely accurate in its assumptions. CS curriculum doesn't touch much on TDD but a pure Software Engineering curriculum does. TDD is not an immediate priority in the education of becoming a computer *scientist*. Now if you want to argue that maybe CS degrees shouldnt be the go-to degree for software engineers, thats an entirely different discussion. Besides, should they be teaching more about git? Powershell or bash commands? Where does this conversation end? Well, thats for the universities (and top tech companies) to decide. – 8protons Jan 03 '20 at 21:58
  • For those CS classes I had which involved writing code, most involved TDD. We were given a set of unit tests and were encouraged to write more ourselves. Our submissions would also be run past an additional set of unit tests as part of the grading. It was a small university that didn't have TAs to do manual grading hence automation. One of the professors was also from a background closer to Computer Engineering and so he liked to think in terms of automated tests. – smithkm Jan 03 '20 at 23:26
  • 5
    Because TDD is a cult. – Miles Rout Jan 07 '20 at 19:08
  • Can I ask, do you have a link to that earlier question? I'd love to read through your answer. – Matt Moran Jan 08 '20 at 15:19
  • @MattMoran: the link is in the question itself. The earlier question was removed, and therefore is visible to high rep users only. Other users may want to use the [page cached by Google](https://webcache.googleusercontent.com/search?q=cache:w65U-_xWacMJ:https://softwareengineering.stackexchange.com/a/403146+&cd=2&hl=en&ct=clnk&gl=us). – Arseni Mourzenko Jan 08 '20 at 17:49
  • 1
    In a data and algorithms class I took, the teacher provided unit tests for most of the assignments. This had the affect of teaching me how to TDD at a time when I wasn't prepared to learn how to write unit tests (especially in C++). That was the best CS class I've ever taken (and most influential on my career); even though the details of the class aren't really useful to me day-to-day, the process was. – Amiel Martin Jan 09 '20 at 21:06
  • @ArseniMourzenko ah - thanks! Much appreciated. – Matt Moran Jan 10 '20 at 10:52
  • *Test your work as soon as possible*. That's the essence of TDD. What the student needs is the means to do so: an interactive language system, leading - when the student tires of repeating tests - to a testing framework. Skill is not bestowed by acronyms or heavy methods (TDD can be but need not be so). Keep it simple. One thing at a time. – Thumbnail Jan 13 '20 at 16:09

14 Answers14

140

I am a part-time programming teacher at a local community college.

The first course that is taught at this college is Java Programming and Algorithms. This is a course that starts with basic loops and conditions, and ends with inheritance, polymorphism and an introduction to collections. All in one semester, to students who have never written a line of code before, an activity that is completely exotic to most of them.

I was invited once to a curriculum review board. The board identified a number of problems with the college's CS curriculum:

  1. Too many programming languages taught.
  2. No courses about the Software Development Life Cycle.
  3. No database courses.
  4. Difficulty in getting credits to transfer to state and local universities, partly because these schools can't agree on a uniform definition for the terms "Computer Science," "Information Technology," and "Software Engineering."

My advice to them? Add a two-semester capstone class to the curriculum where students can write a full-stack application, a course that would cover the entire software development life cycle from gathering requirements to deployment. This would make them hireable at local employers (at the apprentice level).

So where does TDD fit into all of this? I honestly don't know.

In your question, you appear to present TDD as a "problem solving device;" I see TDD mostly as a way to improve the design and testability of code. In the past, TDD has been presented as a "solution discovery mechanism," but even Bob Martin (the principal advocate of TDD) concedes that you must bring a significant amount of prior knowledge to the technique.

In other words, you still have to know how to solve problems in code first. TDD just nudges you in the right general direction relative to software design specifics. That makes it an upper-level course, not a lower-level one.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • 12
    Considering all the other subjects students need to learn as part of the CS and SE degrees, it would be very difficult to fit it in. TDD has enough depth to warrant at least 2-3 credits worth of work. Particularly when you attempt to cover mocks, stubs, theories, parameterized tests, and even more fundamentally what should and should not be tested. – Berin Loritsch Dec 31 '19 at 19:46
  • 6
    Agreed with the fact that TDD is an upper-level course. But TDD does not just "nudge you in the right general direction". Writing tests first is like setting up a line and ruler before mounting a brick wall. It helps you do a better job in less time by transforming after-the-fact repetitive alignment check into a continuous alignment jig. It's better than checking alignment after laying out each brick, which in turn is better than checking alignment after laying out bigger and bigger lumps of bricks. I don't remember my CS degree insist that much that I automate my tests, just that I test. – Laurent LA RIZZA Jan 02 '20 at 13:47
  • Even though I've been coding things professionally for about a decade, I don't really understand what you mean here by "full stack application". Can you explain this bit? It would be extra great if you could phrase it in a way you would explain it to the students on the first lecture of the course. Like what sort of application - a console app, a GUI forms app or a webapp, and what kinds of things it would do, like reading/writing files locally, on the local network, on the internet, over FTP or something, would it use websockets, sqlite, full SQL connections, or did you mean something else? – user1306322 Jan 02 '20 at 15:08
  • 2
    @user1306322: A full-stack application is merely one where the developer understands and can write code in both the frontend and backend of the application. To do that, you have to know a lot of things: HTML, CSS, Javascript, JSON, SQL, ORM, a web framework, and so forth. – Robert Harvey Jan 02 '20 at 15:11
  • 14
    Devil's advocate: Many usages of TDD I have seen actually crippled the architecture, creating tons of unnecessary abstraction layers just for the sake of testability. And the tests themselves were actually a duplication of tested code just for the sake of having tests. Testability is good but often some code is just impossible to test effectively, usually when it heavily uses some external framework (e.g. UI code) and to test it you have to mock the entire framework. Other form of tests (e.g. e2e tests) are then better than unit tests. – Sulthan Jan 02 '20 at 22:51
  • 7
    Writing tests first feels more like first moving people in, and then building the house around them... – memo Jan 03 '20 at 17:19
  • 4
    @memo: More like writing intelligent blueprints that can automatically inspect the house for correctness as construction progresses. – Robert Harvey Jan 03 '20 at 21:17
  • (1) Here in this answer, "Full stack" mostly means "a complete application development life cycle" (or SDLC), not the parlance meaning. (2) TDD any test-driven methodology should be integrated into the capstone project itself and taught alongside. Students need hands-on large project experience first, before they start to appreciate the value of methodologies, including test-driven methodologies. Most capstone projects involve both teaching hours and teamwork hours, so that TDD and project management could be taught and discussed during the teaching hours. – rwong Jan 05 '20 at 19:49
  • "So where does TDD fit into all of this? I honestly don't know." It obviously fits into your point 2, the Software Development Life Cycle. – asmaier Jan 09 '20 at 14:13
  • The difference between TDD zealots and TDD realists is like the difference between political parties in this day and age. Each side is so extreme in their beliefs that conversations between the two usually turn pretty nasty. At the end of the day, if you can convince an organization to pay 150% more for a piece of software in order to pay for the cost of all the extra code then good on you. This is tough in the real world where most decision makers, even CIOs, are looking at short-term bottom lines and don't want to pay for virtuoso development. Personally, I would never work in a TDD shop. – Newclique Jan 09 '20 at 17:14
101

First of all, we have to fundamentally distinguish between Computer Science and Software Engineering. (And maybe to a lesser extent between Software Engineering and Programming or "Coding".)

As one of my CS professors put it: if you need a keyboard, you are not doing CS.

TDD is very much a Software Engineering practice. It doesn't really have much relation to Computer Science. So, if you are asking why CS students don't learn TDD, it's because TDD doesn't really have much to do with CS.

Now, Software Engineering, that is a whole different kettle of fish. I very much agree that TDD should be taught there. I had one Software Engineering class (90 minutes per week for one semester) and in this class we learned Waterfall, V-Model, RUP, CMM, CASE, RAD, Spiral, Iterative, and probably some other stuff that I forgot. Surely, there would have been space to squeeze in TDD, especially if you integrate it with the rest of the courses and apply TDD to all homework and classwork in all courses where programming is required.

To be fair, though, in my case, the Agile Manifesto hadn't been written yet, and TDD was an obscure niche technique.

If you take a look at my personal favorite for teaching programming, How To Design Programs, you will find that they teach very early on that functions should come with usage examples and only slightly later, the book introduces automated unit testing and suggests that those usage examples should be written in the form of tests. They also teach that usage examples and what they call "purpose statements" (you can think of it as the summary line of a JavaDoc comment) should be written before the code.

They don't explicitly teach TDD (they have their own methodology), but this is at least somewhat close. HtDP is designed for high-school students to be taught in less than one year, so I think it is more than feasible to teach it in a single semester in university.

To be honest, though, it would already be a great win of students were simply taught that they can actually run the code they have written with different inputs. (In other words, a crude form of manual testing.) I am amazed at how often students are not able to take this mental step.

For example, I have seen multiple questions on Stack Overflow that essentially amount to "which method do I need to implement to make this code work". Note that this was not about the code of the method (the asker knew how to implement the method), it was purely about the name. However, not one of the askers came up with the idea of simply running the code and looking at the name of the missing method in the NoMethodError exception that will invariably be raised.

Jörg W Mittag
  • 101,921
  • 24
  • 218
  • 318
  • 45
    I agree with `First of all, we have to fundamentally distinguish between Computer Science and Software Engineering.` but (at least in the US) many schools still don't differentiate between the two (or among other disciplines in computing) and graduates of a Computer Science program often end up working in industry with little knowledge of or experience in the practices that one needs to be effective working in teams on complex software systems. – Thomas Owens Dec 31 '19 at 23:53
  • 2
    I can vouch for HTDP, it's used as the curriculum for the first semester CS course at my University. Your grade in that course is directly tied to how well you follow a specific process, part of which is writing the tests before writing a line of implementation. – Daniel M. Jan 01 '20 at 16:39
  • 2
    `First of all, we have to fundamentally distinguish between Computer Science and Software Engineering.` No, I'm sorry, but we don't. The two disciplines simply aren't two axes. They are on the same axis. This distinction became in vogue among academics sometime in the last 15 years, and it is really silly. Especially since it's a CS degree that prepares you for the applied abilities of Software Engineering. Same for Software Engineering vs. Programming. _**No**_ distinction exists. – tgm1024--Monica was mistreated Jan 01 '20 at 20:29
  • 18
    @tgm1024--Monicawasmistreated A CS curriculum typically includes classes on computability theory. While it might be useful for software engineering, it's definitely distinct from SE. Just look at CS(theory).SE vs se.SE. – Daniel M. Jan 01 '20 at 22:53
  • @DanielM., as polite as I can: no. In my over 40 years in the industry, the coding "theory" is applicable or it isn't. If it's applicable, you use it in engineering (design and implementation) of software products. If it isn't, it's pointless. There is no "computing theory" that isn't ultimately software engineering, and vice versa. It's no architect vs builder analog. I see it purely as an invented term. PS. Find someone trained in "software engineering" without computation theory (even if it's not labeled as such), and I'll show you a useless degree. There simply is no such distinction. – tgm1024--Monica was mistreated Jan 02 '20 at 01:49
  • 17
    Sorry, @tgm, but Daniel is correct. There is absolutely a distinction between the two things, no matter how many times you claim there isn't. – Lightness Races in Orbit Jan 02 '20 at 02:16
  • 2
    There may be a distinction, but it's one that's harmful to both the progress of the field and the debt balance of students. – pjc50 Jan 02 '20 at 11:17
  • 13
    I think what's harmful is not recognizing and accounting for the distinction between CS and SE, and pretending it doesn't exist. The most harm is to those students who are told that getting a CS degree will prepare them to be a software engineer. It most certainly does not. – Eric King Jan 02 '20 at 15:16
  • 10
    @pjc50 No. The distinction *just is*. Just like biology and physics are different fields with some degree of intersection, computer science and software engineering are related but different fields. The harm is in *conflating* the two. A lot of students just want to write code, and for that CS is overkill. You have to be actually interested in CS for it to be a recommended career path. – Andres F. Jan 02 '20 at 15:52
  • @EricKing however, if you look at actual courses and hiring practices, SE is less widely available, prestigious institutions prefer to teach CS, and prestigious *employers* like Google prefer CS degrees from places like Stanford (where SE is a sub-course of CS) – pjc50 Jan 02 '20 at 16:52
  • i.e. while it may be the case that SE better prepares you to *do* SE, CS better prepares you to *get a job* doing SE. – pjc50 Jan 02 '20 at 16:53
  • 4
    Whether or not is called engineering is irrelevant. Problem is that many teachers of CS think that engineering is irrelevant. So the danger is that academia sees it as a math field only. People in the CS curiccula can make whatever they want out of it. – joojaa Jan 02 '20 at 18:39
  • @pjc50 Yeah, I agree that if you want a job at Google (and a few other of the big tech companies), there are specific things that they are looking for, and computer science background is one of them. For the other 99% of programming jobs out there, a CS degree from Stanford won't help one bit. edit - ok, maybe a little bit. – Eric King Jan 02 '20 at 20:02
  • 4
    @tgm1024--Monicawasmistreated The typical CS curriculum is almost entirely irrelevant to real world software development. CS grads enter the workforce with so many wrong ideas in their heads that it would actually be easier to make a good programmer out of someone who had never taken a single CS class. – StackOverthrow Jan 02 '20 at 20:20
  • 16
    @tgm1024--Monicawasmistreated Saying CS and SE are fundamentially identical is like saying so for physics and mechanical engineering. One deals in theory and science, the other deals in practice and application. Studying one helps with the other, but they are by no means identical disciplines. – Abion47 Jan 02 '20 at 21:19
  • 1
    By many, Software Engineering is considered a field within computer science (such as my university in Germany, or the Wikipedia authors of the "Computer science" article). What you think "CS" means is likely "theoretical CS", which can be argued, is just a sub-field of pure maths. CS is a cross-discipline field that emerged from (mostly) math and electrical engineering. – adjan Jan 02 '20 at 21:37
  • @ThomasOwens That's true for graduates of _any_ academic university course. The value of such studies lie not in job skills per se, but more so in meta skills, so to speak. – Raphael Jan 03 '20 at 07:37
  • @Adrian There are many parts of theoretical and "theoretical" CS that mathematicians have little to no interest in. Just like there are parts of non-engineering physics that are out of scope for mathematics (at least the whole "scientific method" section). – Raphael Jan 03 '20 at 07:38
  • 1
    @tgm1024: do you think SE.SE and CS.SE should be merged because they have too many common topics or the distinction is not clear? – Doc Brown Jan 03 '20 at 08:51
  • `What you think "CS" means is likely "theoretical CS", which can be argued, is just a sub-field of pure maths.` Well, the argument just got weirder if you think that CS is a sub-field of pure maths (or even math theory). See guys, I'm trying to unwind these "can be argued" concepts. I think the last decade or two has seen more than enough of invented terms and "can be argued" arguments. Anyway, we've landed [here](https://i.kym-cdn.com/photos/images/newsfeed/000/540/686/696.gif). – tgm1024--Monica was mistreated Jan 03 '20 at 14:10
  • @DocBrown _(best handle I've seen in a long time BTW)_, I'm not bothering with that fight. My argument isn't that there are common topics or distinction is not clear. I'm saying there simply is _no_ distinction, and not even in academia settings, however strong it may have become among academics outside of institutions. I'm not entirely sure the impetus behind this rush to word smithing other than perhaps a need to say "I know more", _or_ a genuine innocent ignorance that software engineering does _not_ somehow lack computational theory. It simply can't. – tgm1024--Monica was mistreated Jan 03 '20 at 14:19
  • 1
    Perhaps the best way to put it: Someone versed in high-end computational theory is simply a high-end Software Engineer. You cannot have a high-end Software Engineer ignorant of theory. {shrug}. – tgm1024--Monica was mistreated Jan 03 '20 at 14:22
  • 6
    @tgm1024--Monicawasmistreated Theoretical CS is a subfield of math, yes. It's not "argued", it was actually developed by guys in that field. – Andres F. Jan 03 '20 at 14:44
  • 2
    Saying that computer science is the same as software engineering is the same as saying that theoretical physics is the same as electrical engineering. What are you even talking about? Of course there's the difference, and a major one. – hijarian Jan 03 '20 at 16:55
  • 2
    @tgm1024: you surely meant "your very personal understanding of those two terms is that they mean the same (or art least should)". Well, feel free to see it this way, but don't be astonished if others (especially the ones in academia who create the CS courses without any *practical* software engineering like TDD) think differently. – Doc Brown Jan 03 '20 at 18:11
  • @DocBrown, fair enough, and no worries. I'm hardly astonished about any trends in this discipline any longer. – tgm1024--Monica was mistreated Jan 03 '20 at 19:30
56

TDD is a nice process in "real-world" programming because problems often arrive on our desks underspecified. "Add a feature that does X", "fix the bug where it shows the wrong thing if you do Y", etc. TDD forces us to create a spec before we begin programming.

In CS/programming classes, the problems usually come to us extremely well-specified. "Write a function that takes an array of integers and returns an array with the same integers arranged in non-decreasing order". The spec is handed to us.

I'm curious why you think TDD makes a tricky algorithm problem with a well-defined spec easier. Specifically, I want you to explain this:

I would be mostly clueless if I were asked to compute all the permutations of the elements in a list, still without using TDD. With TDD, on the other hand, I solved the permutations problem in a matter of minutes when writing the answer to the student.

I suspect you'll say because you wrote test cases that asserted P([]) -> [[]], P([1]) -> [[1]], P([1, 2]) -> [[1, 2], [2, 1]], etc, and that caused you to see how the recursion should work. But that's not TDD, that's just... thinking about the problem. You can think about the problem without the process of writing actual unit tests that fail.

MattPutnam
  • 779
  • 4
  • 4
  • 6
    What you described in your last paragraph _is_ TDD. And it being identical to "just thinking about the problem" is the whole point of TDD - it _forces_ you to think through the problem before you actually write it out. It also enables you to employ YAGNI by only writing code you actually need rather than a bunch of other stuff to make it unnecessarily fancy or "scalable". Plus, the non-TDD approach would be to write print or equality statements to verify the output, so the TDD approach, in exchange for only slightly increased verbosity, automatically includes these checks in an organized way. – Abion47 Jan 02 '20 at 21:25
  • 15
    TDD is just the specific process of writing unit tests before writing code. TDD doesn't have a monopoly on thinking. – MattPutnam Jan 03 '20 at 14:33
  • 1
    @MattPutnam, _precisely_, with one "however" from me. TDD as I've seen touted IRL is an absurd overkill. For instance, back when Java _incremental_ test-harnesses were roughly limited to `public static void main()`s sprinkled here and there, I was an advocate of having _many_ such methods. But right now, its turned into a belief system that _every last thing needs to have a unit test first_ which is simply forgetting that they've likely now exceeded the expense of fixing bugs later. Holy moley, everyone should see the extent some folks go through. – tgm1024--Monica was mistreated Jan 03 '20 at 14:39
  • 2
    @MattPutnam That is the "what" behind TDD while ignoring the "why". TDD isn't just about writing tests just for the sake of writing tests. It's the mindset that writing tests before code makes that code safer and more secure, but above all else, it makes it more intentful. The act of writing unit tests forces the developer to write code that has purpose rather than just throwing code around to see what finally sticks, and as such it drastically reduces the need to develop iteratively. Ending up with code that has full test coverage isn't the end goal, it's just the icing on the cake. – Abion47 Jan 03 '20 at 18:35
  • @tgm1024--Monicawasmistreated Every programming paradigm has its uses, but every one also can be abused to the point where the benefits are lost to the zealotry. 100% test coverage is not the ultimate point of TDD, it is merely a possible side effect. People who mix that up end up with code that is highly coupled and virtually impossible to maintain. TDD done well often doesn't quite have 100% test coverage, but it does have code that is concise while also being expressive and well-documented. You also have a vast suite of passing unit tests to show your employers, which makes them happy too. – Abion47 Jan 03 '20 at 18:42
  • 2
    In most all cases, the app is the test. Contrived tests do the exact same thing as the application. It is ridiculous to suggest otherwise. If I have a price calculator that takes in 8 parameters to calculate a price, and the application generates correct prices, test passed. You're not going to generate a test that covers a scenario outside the bounds of the application or else you are not developing to the application spec at all. You're just coding for the sake of coding. The first mars rover crashed and burned because someone used English units instead of metric. TDD is not a panacea. – Newclique Jan 09 '20 at 17:27
  • 1
    +1 Interesting answer! Moreover, TDD has its greatest benefits when the product evolves or is maintained : every change benefit from the existing comprehensive tests to ensure non regression. This is key for real life quality projects. But most university projects are short lived, do not evolve and are not maintained. So nobody sees the advantage. – Christophe Jan 09 '20 at 23:05
33

I suspect it's mostly because writing automated tests is more difficult than writing the code being tested. When you're still struggling with the basic mechanics, it's difficult to add another layer. Also, as other answers have pointed out, TDD is perceived as a software engineering process, even though its practitioners think of it more as a didactic device. Also, knowing what tests to write first is a skill in itself.

If I were teaching an introductory course, I would provide some tests in TDD order, and instruct the students to get the tests passing one at a time in that order. That's a very similar experience to pair programming with an experienced mentor. Personally, I think it would make classes like algorithms easier to teach, which would offset the time spent on the technique, because of the step-by-step progression. It would get students thinking about questions like, "I have some proven working code that will find all the permutations of a two-element list. How do I reuse as much of that code as possible to make it work for 3+ elements?"

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479
  • 13
    As a "didactic device," unit tests have a pretty high barrier to entry. It's hard to get that right, and it presumes a lot of prior knowledge. I like your idea of providing pre-written unit tests to students. – Robert Harvey Dec 31 '19 at 23:04
  • 4
    But the students need to know that just testing each specific requirement is insufficient. Users are going to do things the spec writer did not anticipate. Someone once claimed my bug report must be a mistake because no one had ever reported it in the already long length of the project. My retort: “then I guess no one has ever made a right turn with the type of vehicle.” Just one of the many times I found a fault by a random deviation from a test script. I’ve also cleaned up after a coder who implemented a requirement to do X by writing code to make sure it wouldn’t do anything else! – WGroleau Jan 01 '20 at 17:50
  • @WGroleau then you introduce the didactic device of the [EnterpriseDeveloperFromHell](https://fsharpforfunandprofit.com/posts/property-based-testing/), who provides programs that pass all the tests but are as useless as possible. – Caleth Jan 02 '20 at 12:14
  • 1
    How exactly is writing automated tests harder than writing the code being tested? IMO it's not harder, it's a different, complementary skill. Writing automated tests forces you to take decisions about what results you actually want, which to me is the harder part. – Laurent LA RIZZA Jan 02 '20 at 12:27
  • "Automated tests" is ambiguous. _Running_ tests can be automated, or _creating_ tests can be automated. More than once I have reviewed tools that were advertised as automatically creating test drivers. Every one of them analyzed source code and created test cases that could only fail if a compiler bug existed. – WGroleau Jan 02 '20 at 16:45
  • providing tests with the goal of making them pass is an excellent compromise, with the added benefit of making assignments potentially easier to grade. common in the interview process as well – aw04 Jan 02 '20 at 18:00
  • @KarlBielefeldt, I was part of a consulting organization decades ago who had vehemently come to the conclusion that Rapid Prototyping (the in-vogue technique of the time) was a huge waste of time. What you said here: `I suspect it's mostly because writing automated tests is more difficult than writing the code being tested.` grabs my attention. If what you meant by this was _"it more often than not becomes counter-productive"_, then your statement applies _perfectly_ to more than just TDD. – tgm1024--Monica was mistreated Jan 09 '20 at 16:11
9

The average student really has a bad overview of what they are expected to know and do. To teach TDD they would need to understand:

  1. How to troubleshoot technical problems. In the beginning they think code is written in one go. Its only later when they realize basic debugging strategies that they move over to more incremental writing. Even if you tell them this up front they will still do it this way because they think that's the way things are done (this is by the way also why people don't know how to draw, play piano, do math, etc etc.)

  2. How to introspect your own actions so that you can find repeatable patterns in your own behavior. Once you can do this you can automate your own work. But this is utterly alien to most people until they reach a certain level.

  3. How to write requirements.

  4. Understanding corner cases of your problem space.

  5. Understanding engineering philosophy on management on risks. (ha but you don't even know you're an engineer right)

  6. Understanding refactoring and maintenance of code.

  7. Understanding how programming works in a real company.

In fact I have had colleagues who were introduced to TDD way too soon, they didn't really benefit all that much. However, it is still possible to take baby steps towards this effect. Its just that people need quite some experience behind them to benefit.

So you can teach it but not something you start with. Especially since there is code that does not lend itself to TDD very easily.

Uyghur Lives Matter
  • 126
  • 1
  • 1
  • 10
joojaa
  • 349
  • 1
  • 11
  • That is a great list of things to teach students who want to work as software develpers. It would be nice of courses had a real life software module that had experiences from former students. – Paul McCarthy Jan 14 '20 at 22:39
9

The basic issue is that inventing the tests in the TDD process has nothing to do with computer science or software engineering. It requires knowledge of the application domain.

Of course that is the strength of TDD in real world applications: you can't escape from thinking about what the system you are building is actually going to be used for. But in typical CS and SE activities, the tasks the student is given have minimal context, and exist only to test or illustrate some learning objective.

For example, if the learning objective is to demonstrate understanding of the "case" construct in a programming language, TDD is irrelevant: you can write software that passes all the TDD tests without using "case" at all. If the example was artificial, not using "case" might in fact be a better solution to the problem in the real world, but though not in terms of the learning objective that was intended.

By all means encourage students to invent their own test cases and run them, but trying to use a formal TDD process is beside the point.

A second issue might be more to do with the way CE and SE are taught, but it is still a practical one: how to you grade the student's collection of tests when using TDD? There is no obvious way to automate that process.

Even if you produce a model solution which says "you should have tested for the following 15 or 20 situations" you still have to manually identify which of the student's tests corresponds (wholly or partially) to each part of your model answer. And except in trivial cases, the student might have produced a good set of tests that are logically structured in a different way from the model answer.

alephzero
  • 1,269
  • 1
  • 8
  • 8
  • Maybe I misunderstand your second point. It seems to me that evaluating the rigor of a set of tests is quite simple to automate - by running them against each of a canned set of implementations each with a specific known bug, and determining if there are test failures (as would be expected). Just like one might run a canned set of tests against a student's implementation to evaluate the accuracy of that implementation. – starchild Jan 02 '20 at 08:56
  • 4
    @starchild for same reason that this is hard to do in reality. Your still only testing some corner cases. So what if the student has found 7 valid corner cases whereas you have found 10 but only 5 of the corner cases between you and the student match. So your automated grading now gives student 5/10 whereas it should be giving 7/10. Or 7/12 and all others scores should be lowered? – joojaa Jan 02 '20 at 10:13
  • `The basic issue is that inventing the tests in the TDD process has nothing to do with computer science or software engineering. It requires knowledge of the application domain.` I believe you're confusing _Functional Requirements_ and _Design Requirements_. TDD is about the implementation of a particular design. When TDD proponents (I'm _**not**_ one) refer to functionality, they're talking at the implementation phase, not application level functionality. "Does this sort routine work?---Make a test for it first, have it fail, and _then_ implement it.", (etc.) – tgm1024--Monica was mistreated Jan 03 '20 at 16:59
6

TDD is not more popular in universities, because (generally speaking) universities do a very poor job in ensuring that the knowledge that is being given to the students can be transpiled to real-world contexts.

Arguably, that is not the role of university in the first place, and, it's more about teaching the fundamentals and core concepts of CS. That is instructive, important, and, essential, if the students would be interested in pursuing a career in academia, but, it falls short when the students will finish their degrees and enroll in the industry, working integrated in a team, that follows development best practices, CI/CD, etc.

Obviously, there are intersections and both can benefit from each other, but, ultimately, university is simply not yet up to speed with what needs to be done to graduate more capable, relevant, and up-to-date software engineers.

Bruno Oliveira
  • 503
  • 3
  • 4
  • Great answer, Bruno. E Feliz Ano Novo, homem. – Trunk Jan 03 '20 at 15:25
  • Which is why code camps could be a better preparation for a career in programming. And many can self-teach and land a job based on actual apps they have developed and published. Degrees aren't always the answer. – AlanKley Jan 08 '20 at 17:46
  • To put things in perspective, CS != SE (see https://softwareengineering.stackexchange.com/a/403153/93338) so CS falling short of the industry trends is not particularly surprising (specially since a lot of innovation seems to come from outside the academy within the SE field). Also, if you are careful about the terminology, SE != software development != programming != coding. – Piovezan Feb 06 '21 at 01:56
4

I never considered TDD helpful as a way to actually solve a problem and after reading your question I still don't.

TDD merely forces you to look at a problem from one end: the client's end. This can help prevent you to come up with a solution that does not match the client's question. This is generally a good thing, although it could also limit you, it keeps you from looking at the problem from a wider angle, there may be a better, more general solution to the problem your client did not consider.

Another way to look at it is that it is the ultimate top down approach. TDD could stand for Top Down Development. You start development at the most course level and gradually zoom in.

Either way, it is an abstract concept. You can tell a student about it, provide a definition, but that will be it. You cannot ask that many questions about it in an exam. So in any SE or CS class, although useful in a SE context, it could never be more than a side note.

Martin Maat
  • 18,218
  • 3
  • 30
  • 57
4

To answer the question directly:

As someone suggested, there's enough learning for a whole semester. A separate course? Maybe. I could see TDD being combined with software design topics. IMO TDD's greatest value is locking down existing behaviors so we can add new behaviors later, and change the design to be appropriate for those new behaviors. So a software design class?

It would be nice to see the thinking process behind TDD (poorly named, and I once asked Kent Beck if he'd reconsider; he said "that train has left the station") be introduced as early as possible. I've been slinging code since 1976, and I know that TDD felt very unnatural at first. But now it feels quite natural. My time isn't recouped by writing test code, it's recouped later, when I only have to fix a serious defect once per year (The UofM Transplant Center's OTIS2 software, written entirely test-driven, had its last "software emergency" in 2004).

I encourage fresh graduates to try it out for a month. But it would be so much easier on them if they were exposed to TDD much earlier. I find using the unit-test framework useful when I'm learning a new language (True story: "Now how do I get this test to pass in Ruby? MAYBE this will work...HEY IT WORKED!"), or exploring a new library ("The docs are vague about the order these will be returned...I'll write a test...").

I find TDD valuable when implementing an algorithm (NOT inventing one...I'll get to that), or building any mildly complicated business rule from the ground up, as it were. Each test that is passing is "locked in" for all eternity. If the test is discrete enough, it won't ever have to change (but that takes a lot longer than a month to get good at).

So it would be interesting to incorporate TDD into earlier programming classes. Three points of improvement:

  1. We could focus less on debugging and break-fix, which most developers think is just the nature of their job. It ain't. It doesn't have to be that painful or time-consuming.
  2. Unit test frameworks are a simple replacement for #ifdef DEBUG / printf("...") / #endif - so we've been doing something similar (but more risky) since the beginning of time.
  3. When we hear "you MUST write the test first" we're being mislead. I want to write down my expectations for the code I'm about to write. I want to leave that running while I go focus on the next behavior, or on cleaning up the design.

Another thing that might be useful is a textbook or, at the very least, a condensed no-nonsense curriculum with labs designed to convey various aspects of the TDD practice. I have a suggestion for that (see experience/disclaimer later).

To answer the critics:

I'm new here, but I note that some "answers" don't answer the question, but are fair critiques of TDD. So I'm guessing it's okay to address some of those concerns?

  1. It's true, studies that have been done comparing TDD to unit-test-after (UTA?) show that TDD was initially slower. However, the UTA group had much lower test-coverage, and more defects. I think it was this study: Longitudinal Study of the Use of a Test-Driven Development Practice in Industry

If developers working on a product for more than a few months were really spending the majority of their time writing new features, then this would be a negative. But the six TDD teams that I worked on as a developer did spend their time that way, whereas the decade I spent slinging code prior to TDD were spent mostly in the debugger, or cautiously copying/pasting/modifying so I wouldn't break older/someone else's code. The benefits of TDD aren't all instantaneous, but they've been remarkably reliable and amazingly valuable as measured by lower developer overtime (and stress) and increased revenues. Bottom line: I always looked forward to going to work with those TDD teams. (Once I'd had some tea.)

  1. It's also true that TDD cannot invent a new algorithm. I think it was Ron Jeffries who tried to create a Sudoku solver using TDD, and tried not to let his own Sudoku skills interfere with the implementation. He failed. I'm not surprised. TDD helps break down, simplify, and implement business rules; helps confirm we got an algorithm right (e.g., a complex encryption algorithm that may not be reducible); helps us reshape code later so that we can safely add new features; and does this by pinning down the investment we've already made in the behaviors of the product.

When you write a "test" (aka specification, aka scenario) you have to know the answer! Also, you want to write a test that is a small enough bite out of the solution that you already have some notion (prior knowledge) of how you are going to implement it.

What is often a surprise is how clear and simple the design can become if we pay attention to code-smells and we refactor as needed whenever all the tests related to that code are passing.

No one is suggesting we throw out our good knowledge of design patterns, or language idioms, or SOLID principles, or how to play Sudoku, or how to write a heap-sort.

TDD is about creating a safety-net that gives us confidence to rapidly add new features and alter the design to fit those new features without breaking anything else.

UTA is patching the safety net after someone falls through a hole to their death. (Interesting side note: The OTIS2 project is a life-critical system, so the risk of patient death wasn't a joke to us. Over 20,000 tests all running in 10 minutes, now that is a safetynet!)

Experience/disclaimers:

I did TDD pretty much full time from 1998 to 2004 and with ~6 different teams. All were at least 6 months of development. Before that, I had spent 13 years writing software the other way, and came to hate debuggers and manual testing with printf().

I started teaching software development practices in 2001, now including TDD, BDD, and SA-CSD courses. Sure, it's a good living, but I also know that TDD is a straightforward way to make team-centric software development sane and enjoyable again. So...

I'm writing what I hope will become a college or high-school textbook (with online repos, labs, videos, etc, of course): Essential Test-Driven Development

Uncle Troy
  • 149
  • 3
4

I was taught computing science in the 1970s, long before the acronym TDD was invented, and of course we were never explicitly taught the technique. But for one of the programming exercises we were given, we were supplied with a set of test cases and were told that our solution had to pass the tests. So I learnt the value of the approach without ever being taught it explicitly, and have used it ever since.

Michael Kay
  • 3,360
  • 1
  • 15
  • 13
3

While writing tests is an essential skill for software development, the scientific evidence does not indicate that TDD ends up producing any better software than iterative test-last (ITL) development (OTOH, it also isn't worse).

For evidence, you can see Davide Fucci et al. "An External Replication on the Effects of Test-driven Development Using a Multi-site Blind Analysis Approach" (link) and Turhan et al's meta-analysis in Making Software (link).

So, unless we start seeing evidence to the contrary that TDD does, in fact, provide measurable gains it's less important that TDD as a specific practice is taught as opposed to simply instilling the good habit of test writing at some point in the development process.

Anzel
  • 39
  • 2
  • 1
    Well, some would say that in theory there is no difference between theory and practice... . It's a whole different think to look at the theoretical performance of a few (unexperienced) students on projects that will never be maintained, and to look at practical results in real CI/CD projects with teams twice as large as the number of students involved in that experiment. Being understood that the main difference between both approach will be observed in the maintenance and evolution and not in the first release. – Christophe Jan 09 '20 at 22:59
  • 1
    There are numerous studies in Turhan's meta-analysis that work with postgraduate and professional workers, and the evidence for the effectiveness of TDD is still inconclusive. If TDD practitioners wish to make their case, they will need to up their level of evidence to show a real effect. The plural of anecdote is not data. – Anzel Jan 10 '20 at 15:03
2

but I would still spend some time writing a list-ordering algorithm without TDD, if asked, and I would be mostly clueless if I were asked to compute all the permutations of the elements in a list, still without using TDD. With TDD, on the other hand, I solved the permutations problem in a matter of minutes

This is confusing me seriously.
To me test driven development means to think about tests early and take the time to implement tests and keep them up to date with code.
Of course thinking about what to test is a good chance to elaborate the problem to solve and in some cases get a good picture of what the pitfalls are.
But not doing TDD, not concentrating on tests first doesn't forbid to think about the underlying problem anyway. You always should think about what you do and make the situation clear, no matter if you want to go one more step and implement tests right now or not.

would it be problematic to explain the TDD approach before asking students to write list sorting algorithms and similar stuff?

It depends to which extent you would explain TDD.
It's helpful to hear about something. But students hear a lot of stuff they can't yet interprete because other basics are still missing. So you shouldn't go too deep into a concept that without knowledge of basics would be a useless and alienating mess of unknown terms to them.
Besides this probably many programmers know what it feels like if you are looking for a how-to on some problem and find examples that indeed show a solution but first of all you have to sort out all kind of other irrelevant stuff the author added.

So to answer this question, if I was a student I'd like to have things separated. If you announce to explain us how to sort a list then please do tell us how to do that but don't leave the path to fill in testing stuff. If you want to start explaining tests then don't announce to implement sorting because this still doesn't happen for a long time.
Again there is some thinking required before we start to write the sorting or tests. What do lists look before and after sorting? Make examples, think about pitfalls, what must be considered to avoid failing when a list is empty and so on. All this must be considered but no line of tests is written yet.

Generally I'd say you are mixing up two things that should be kept seperately.

  • Thinking about the nature of the problem you want to solve.
  • Thinking about input to your code and what output should be given.

Thinking about the problem is very different from focusing on writing test cases.

How to do it bad

Once I came across an example of TDD by someone who was sort of obsessed with TDD.
Unfortunately it appeared to me the author was too fond of his tutorial so he didn't realize what crap it actually was.

The author only concentrated on test cases, not on the problem their code should handle. As you never can find all input permutations, you must have an overview of what you are actually doing, you must see the entirety of the problem. You can't always start with empty input, then subsequently add some more input and always append code to handle new input correctly.
You must have an idea what you're actually dealing with in general. But the author didn't.

If I try to translate it to sorting a list, we'd start with an empty list, then one element that can be returned as it is, a list with two elements that perhaps need to be swapped and perhaps end up in a recursion because three elements is like two (we already solved that) plus one more with one extra step...
A horrible szenario for a sorting algorithm- but noone will realize it because we only concentrate on out test cases.

Conclusion

The comments make me write a little more about my opinion.

I think the term "test driven development" is wrong. It should be "test-supported development", meaning we don't just code and hope but we think about testing too and we know it's always good to know early when something goes wrong.

If development is named driven by tests this could imply everything depends only on tests and we are done as soon as a couple of test cases are satisfied. This requiremend would be met even by very insufficient code that never tried to see a problem as a whole but got hacked back and forth until all test cases acidentally turn to green - then fails in real operation.

puck
  • 181
  • 3
  • Yeah, I was always doubtful about the idea of just adding enough code to satisfy the test. This is fine for boundary value tests. But useless if you're testing a continuous range. Can't just put in a statement dealing with a single mid-range value and then another and another, etc. Seemed to me that TDD is only effective where a separate test team write the tests and the sequence in which they are achieved by the code. – Trunk Jan 03 '20 at 15:31
  • 1
    @Trunk tests can help the developer too, the one who writes code can think more detailed about his code and perhaps finds pitfalls that should pass a test. Furthermore tests can help avoid that code changes open another pitfall. What I want to emphasize is, don't rely on tests only. Tests are not the one and only salvation. Don't stop thinking about code, absolutely don't produce bulls..t code that is "good enough" if only it passes some test cases and ignores the whole rest. To me tests should be a supplement to coding, but not an entire coding method that allows leaving everything else out. – puck Jan 03 '20 at 16:15
  • Tests WILL certainly help the developer for sure. But I doubt if following a testing procedure that follows the TDD process strictly will be beneficial to coders. It's likely they will (like many more of us) just evolve their own way of writing preliminary tests and sequence of running them as they code. – Trunk Jan 06 '20 at 15:39
  • 1
    @Trunk the distinction really is that you *do* just add enough code to satisfy the test, but you have to do so in good faith. You write the test to represent the test case and then you implement the code to satisfy the test *case*, not some contrived attempt to make the test green but undermine the process. What gives you the confidence is then the consistency between your intuitive understanding of the test case and the automated verification of the test - *not* the test alone, which can always be fooled. – Ant P Jan 07 '20 at 08:43
  • 1
    The mistake that the "purist" crowd makes is trying to treat TDD as a rigorously formal process, which it isn't - it's a technique, which has to be applied with intuition. – Ant P Jan 07 '20 at 08:44
  • Well, okay but *writing the test case to represent the test case* is the nub of the issue, I think. If the TDD gurus agreed with this they should have made it explicit in their commandments ! Though I do take your point that coders have to wise up to meaningful testing for themselves - they can't expect testers in their company to slowly surrender their salary differential by teaching them all their tricks - that'd be like turkeys voting for a second annual Christmas ! – Trunk Jan 07 '20 at 11:41
  • 1
    @Trunk I think the original idea of TDD has been somewhat skewed and misrepresented over the years into something of a dark art. TDD doesn't seek to replace manual testers, the two things serve very different purposes. Ultimately TDD exists to help me write code that I'm confident in, which is a much narrower scope than what a QA person is interested in. – Ant P Jan 07 '20 at 13:26
  • @Ant P : Yeah it's been interpreted in varying ways to say the least. Just like Agile/Scrum. Met a project management trainer one time who claimed Agile PM could be applied to all sorts of projects in software, hard engineering, even legal projects . . . – Trunk Jan 07 '20 at 14:46
1

You've updated your question to be more "Why isn't TDD not taught as a core learning tool?". Other answers already explain well enough why TDD isn't a good topic for coding 101, but the main answer is really just that TDD, at its core, is not a problem solving tool. It can be used for that purpose, but like any tool you have to first understand when and how to use it.

TDD is a testing process, and thus most naturally will be taught either as part of a Development Processes course, or as part of a Software Testing course. In coding 101 courses, the goal isn't for students to solve problems, it's to teach them how to use various programming concepts. Generally, most coding 101 and 102 projects will be very explicit about how to solve the problem, the students just need to understand what they have learned to do the task in a non copy-paste kinda way.

Every student learns in different ways. Some students need to read about it, others need it verbally explained to them, and others will just never get it unless they get neck deep in code. Teaching TDD to aid in the learning process will not actually help most students, and the ones it does help? Teachers will have to decide if the time to teach TDD was worth the extra learning speed. On a net whole, teaching any learning method will not be worth the class time that could be spent on actual course specific topics. (In general, learning and problem solving skills are usually left to students to learn themselves, since only the student can identify what works best for them)

TL:RD; Different people have different effective processes. Universities don't prescribe how you should do anything; Just give you the tools so you can do what works best for you.

Tezra
  • 238
  • 1
  • 10
  • `TDD is a testing process, and thus most naturally will be taught either as part of a Development Processes course, or as part of a Software Testing course.` The very start and end of your statement are incorrect. TDD is _not_ a "testing process". It's a _developement process_ that involves testing. The distinction isn't mundane: A testing process is something that _has something first_ and then establishes a process to test it. TDD is about creating that thing in the first place (by _employing_ testing). It would never be taught in a Testing course. – tgm1024--Monica was mistreated Mar 09 '20 at 15:48
  • @tgm1024--Monicawasmistreated a testing process doesn't need something to exist yet. For example you can develop user stories that the final product can pass before development even starts. TDD just changes the order things are done, but the key part is still the Testing. The process part of it would be covered at a high level in a Dev-Proc class, and the low level actual automated test writing for TDD would be covered in a Testing class. (and that's how it was taught at my college) I would also argue to try not to focus on the exact words used too much, because they aren't standardized. YMMV – Tezra Mar 09 '20 at 16:21
  • No, again, that's not a testing process, and I know what the ordering in TDD is. You're still missing the fact that TDD is not a testing process, but merely puts testing as a component of a _development_ process. The steps in TDD are not to test something. They are to _create_ something: The way that they do this is to establish a test first. A _testing process_ would be akin to listing out functional specifications and verifying that each works, and then regression testing to make sure they didn't walk you backward. THAT'S a testing process. You don't even need developers for it at all. – tgm1024--Monica was mistreated Mar 11 '20 at 00:12
  • @tgm1024--Monicawasmistreated You seem to be missing missing the fact that the words you are using are not standardized. The general consensus of what they mean has been changing constantly since software development became a thing. The point of this answer is that TDD is a tool, and like any other tool it has a time and a place but is not automatically good for everyone. Don't worry about the semantics of the words used. Focus on the general point. – Tezra Mar 11 '20 at 12:10
  • It's by definition a semantic concern when you're using the wrong term, and yes the terms are standardized; I have no idea why you're stubbornly holding onto this misinformation. Here, I'll spell it out differently for you: A QA engineer is trained in _testing techniques_ and _testing processes_. A QA engineer would _never_ venture anywhere near TDD, because they don't deal in _development processes_. That's for software engineers. – tgm1024--Monica was mistreated Mar 15 '20 at 14:26
  • Look, you seem convinced that this is a trivial distinction. I'm convinced that you're going to mislead some junior engineer somewhere (IMO less than 10 years professional) or some student somewhere. So that impasse is where it ends. – tgm1024--Monica was mistreated Mar 15 '20 at 14:31
1

TDD is a fantastic implementation tool, and I think you are correct about it being beneficial to those who wish to write software.

What is the reason TDD is either not taught at all or at least very late in universities? In other words, would it be problematic to explain the TDD approach before asking students to write list sorting algorithms and similar stuff?

Probably the biggest reason is that the professors teaching these programs rarely know how to develop software, since that isn't their field of expertise. As other answers have mentioned, computer science and software engineering are different disciplines, and I would compare the expectation that computer science students learn software engineering to physics students learning how to design cars. TDD is a skill that takes a decent amount of practice to really be able to teach effectively, and computer science professors spend the bulk of their career working on computer science, so expecting the computer science faculty to really be able to teach TDD in a way that won't merely confuse their students is pretty unrealistic in my opinion.

We need to treat computer science and professional software development as the distinctly separate fields that they are. If your goal is to learn computer science, you should not be burdened with paying thousands of dollars learning how to make websites in React incorrectly from someone who has spent the last 30 years of their career doing graph theory on a chalk board. Likewise, if your goal is to become a software engineer, I don't know why you would want to spend 4 years and tens of thousands of dollars learning what is essentially just a specific field of mathematics. It's good to have a foundational understanding in the field, just like how someone designing an exhaust manifold needs to understand some amount of physics, however the person designing the exhaust manifold doesn't need too in-depth of an understanding in quantum mechanics, special relativity, and electromagnetism to do their job.

If you want to be an accountant, you can go get a degree in accounting and your professors will likely all have been CPAs at one point or another. If you want to be a mechanical engineer, you can get a degree in mechanical engineering and your professors will likely all have been licensed engineers at one point or another. But if you want to be a software engineer, any degree in software engineering will actually just be a computer science degree with some of your electives already chosen for you, and almost none of your professors will ever have been professional software developers. The accounting degree isn't part of the math department, and the mechanical engineering degree isn't part of the physics department, but the software engineering degree will almost always be part of the computer science department. Until academia as a whole completely separates these two fields into different departments run by different staff, I think there will always be a long list of things like TDD that are not taught to students aspiring to be software engineers.

Dogs
  • 1,166
  • 7
  • 11
  • It may be true that professors "rarely" know how to develop software, but you can't pin any observed pushback on TDD on that. I've been a professional programmer for 40 years. I'm also _not a fan_ of it, for the reasons I elaborate on in comments. It's yet another trend (similar to extreme programming) that showed up supposedly as a "tada!" moment, that ultimately shot itself in the foot by forgetting the bottom line: Are you spending more time in component-to-component developement now than you would otherwise be spending in unit testing prior to release? – tgm1024--Monica was mistreated Mar 09 '20 at 15:53
  • IOW, if you're good at TDD, you're _already_ good at the fundamentals of unit testing. If you weren't, any of your pre-tests you came up with during component level development would be similarly weak. Not necessarily specific to you, but if you've only been in the game a couple decades or so, it's particularly difficult to see how trends come and go, and more so: Why they do. – tgm1024--Monica was mistreated Mar 09 '20 at 15:55