I understand the advantages of test-driven development, but should unit testing be taught/used in CS1 (the introductory class) for computer science students learning?

I am aware of researchers saying that "YES" it can and should be taught, but in the "real world", is anyone using it in their CS1 classes? Do the students write the tests or are they provided with the assignments?

$\begingroup$Welcome to CSEducators.SE! Can you provide a little more context to your CS1 class? Language(s)? Background of students? Demographics? Path for students after that class? The more specific the information, the better the answers will be!$\endgroup$
– Peter♦Jun 21 '17 at 14:44

$\begingroup$thesecretmaster, I understand your point, but that target students are different, and I am not asking "what could be done", but "if this should be done".$\endgroup$
– Nuno Gil FonsecaJun 21 '17 at 15:32

1

$\begingroup$Not everyone knows that CS1 means the intro course for college majors. You might want to make that explicit.$\endgroup$
– Ellen SpertusJun 21 '17 at 21:25

6 Answers
6

I'll assume that you mean a first programming course that uses a language (Java...) that has well integrated testing tools.

If you just use unit testing as an add-on then I'd guess the proper answer is no. There are other things the student could be doing.

However, if you are willing and able to modify your teaching a bit then unit testing can be a big win. I've used it in teaching introductory programming to adults for years (since back when Extreme Programming was young).

I do two things. First, I give out assignments differently at the beginning. Rather than giving students a narrative to describe a programming exercise or project, in which they must first decompose the description into tasks, I give them the task list itself. In Agile Programming language, I give them a small product backlog or story-card deck. The tasks are numbered in a logical (do this first) order so that when the backlog is completed the project is done.

Therefore I'm using a bit more than just unit testing. Other "personal" agile programming practices are employed, including pair programming. I also act at the student's Customer, answering questions as needed.

The second thing I do: On the first day of class I do a demo project in public. I start with a small number of "stories"; tasks that decompose a simple project. I pick out a student (volunteer or other) and we pair program on a laptop connected to a projector so all can watch. I start out as the "driver" with control of the keyboard and my student is the "navigator". He or she may know nothing of programming, or very little. We look at the first story, discuss it a bit to get a "picture"/analogy/metaphor. I then fire up Eclipse, start a new project add JUnit to the project and write a test for just that one card. It fails of course. So then we (my nav and I) write app code to make that test pass. Repeat. At some point we switch roles and the student becomes driver and I act as a very helpful navigator. If the class isn't too large you can also open "navigation" (comments, questions,...) to the class as a whole, to get them used to the process of aiding the driver.

Along the way I discuss what we are doing at each step (go "meta"). This can take up much of the period, but if you have enough time you can distribute the code you've done to the class. They can pair and work on the next story as you wander about giving help.

So, they see unit testing and pair programming and build on the test-first philosophy in an integrated way.

Another thing, that works well with this is that, when you assign them a project, you can give out a unit test suite along with the product backlog. In other words, you write the unit tests and they make them pass. The down side of this, however, is that the tests contain identifiers from the app (class and method names for example). In the big picture, the test suite is your low-level design space where you decide on such things. If you write a test for the "increment" method, you will normally do it before you even have a stub for the method. In writing the tests you discover the name as well as the args it should have and its return type. If you give the tests initially you have already done this step and so need to teach it a bit later. Maybe by the 3rd exercise.

I'm going to start my answer the same way as the only other answer so far and say it depends on the context of the course, but head in a different direction.

The fact that you're calling the course CS1 implies that it's the start of a chain or tree of courses. A CS1 for a traditional theoretical CS course of study will be different than a CS1 for a newer style programming-oriented program will be different than a CS1 for a "zero to job-ready" boot camp.

A more traditional curriculum likely won't involve unit testing, as it will focus more on theory and algorithms and less on practical coding. The newer, more hands-on ones involve a component of learning good practices for both programming in general and usually specific languages as well, and so some coverage of unit testing is often appropriate.

Even if you remain in the (now-minority) group of people who aren't convinced of the wonders of developers adhering to Test-Driven Development (TDD), it's a concept that most developers are at least familiar with, so it's important to make your students aware of it (if not in CS1 then at some point).

For a real-world example: the semi-famous UC Berkeley Engineering Software as a Service intro-level course, which has been MOOC-ed, and its award-winning accompanying book, covers unit testing quite heavily.

$\begingroup$Nice answer. Welcome to CSE! I hope we hear more from you in the future.$\endgroup$
– Ben I.♦Jun 21 '17 at 18:26

$\begingroup$Piyush Parikh, I deal more frequently with the "traditional curriculum" (I myself, never learned unit testing in the University). But fully understand the advantages of using unit tests. The thing is that even in "zero to job-ready" courses using Java, I don't see the teachers using unit testing. Maybe it is a cultural issue...$\endgroup$
– Nuno Gil FonsecaJun 21 '17 at 19:19

The student projects might not lend themselves to TDD in that the early assignments will probably be very small and if the end up writing 90% of the project as tests and 10% as their stuff it could be deflating.

That said, they should at least be familiar with TDD but that doesn't mean it has to or should be in CS1. The most important thing to get across early w/r to testing is not TDD in particular but the importance of thorough testing. I've never been a big TDD person but that doesn't mean I Don't test my code constantly throughout development - that's the important concept.

What might be a good idea is to expose them to TDD in that when you give an assigment, give it with the tests / test framework. I played with this a little last year and plan to do it more next year.

When giving a lab or homework, give it with the tests - kindof like having them use an online grader but they get and see the grader.

Later on, if time and projects permit, they can add some of their own tests or perhaps even do the TDD thing whole hog.

$\begingroup$Mike, you kind of answered the question that I should have done! :) In introductory classes you can provide the tests as part of the assignments. This is one approach that I've seen previously!$\endgroup$
– Nuno Gil FonsecaJun 21 '17 at 21:33

That depends entirely on the context of your CS1 course. Are you teaching unit testing suite to your students? If you haven't learned something then how can you use it? If unittest is part of the curriculum, then definitely students should use it. At my University, students are formally introduced to the JUnit suite during 2nd year, and thus for all their Java projects they are required to have their own testing suite. As for their C projects, we do not require unittesting because gdb is already enough hair pulling.

So to answer your question, no we are not using unit testing in CS1 because it has not been formally taught yet.

Yes, but introduce it one step at a time (Zone of Proximal Development).

Manual testing is the absolute minimum, needed to know if you have written the program that you intend to (feedback). Incrementally adding to a program is the only effective way to get a program to work (quick feedback). Therefore as least to manual TDD, from the start.