# How to stress the importance of testing code?

I've run into the issue in the past that students don't test their code, and get into a huge mess when they can't find out what's not working. How can I prove to them (before something like this happens) that testing code is important?

This is a class of high school students, grades 9-12 (ages 14-18). The class is mostly made up of sophomores, but has students from all grade levels.

This is in the United States.

• Could you tell us what's the age or level of the students? – ItamarG3 Jun 20 '17 at 16:02
• @ItamarGreen - this is a class of high schoolers, mostly sophomore but a mix of grades 9-12 – Jackson1442 Jun 20 '17 at 16:04
• Could you edit your question to include that information? perhaps use the high-school tag to make it clear for readers. – ItamarG3 Jun 20 '17 at 16:05
• @Jackson1442. I have no idea what "grade 9" means. Ideally, give us an age range. Failing that, at least tell us what country you're in, so I can go look up your schooling system and edit that information into the question myself. – TRiG Jun 20 '17 at 17:17
• Have them contemplate the famous D.E.Knuth quote: "Beware of bugs in the above code; I have only proved it correct, not tried it." – Hagen von Eitzen Jun 21 '17 at 9:47

Introduce test-driven development.

TDD and agile methods of development are very popular at the minute, and for good reason — you know, ahead of time, exactly what each part of the program must achieve, and you can confidently say that the program will work as intended as long as your tests are thorough.

I think that sometimes, the confusion begins when students aren't actually sure what they're trying to achieve in the first place, so they're reluctant to test because the code is already so fragile. TDD helps to ensure that there is a clear specification of behaviour for the code, so the students are clear on what should happen, and that the code they're written fulfils the specification.

Make it clear that testing is part of the project in your lessons, and it should help to solve some problems. When students are asked to write a program, they may not realise that writing some tests along with the project (or even beforehand, as in TDD) is a good idea. Having the red-green-refactor cycle would seem helpful here; it will give your students confidence that their code works as intended, and then the ability to clean up and improve their code without breaking it.

Test-Driven Development Goes To School was interesting reading while I wrote this answer. They evaluated the effects of teaching using TDD at several university courses, with generally mixed/positive results. At Virginia Polytechnic Institute:

• Code correctness measured as the number of defects per thousand lines of code was only 38 for the TDD group compared to 70 for those not using test-driven development
• 65.3% of students either agreed or strongly agreed that TDD increased their confidence in the correctness of their code.
• 67.3% either agreed or strongly agreed that TDD increased their confidence when making changes to their code base.
• Test completeness was 93.6% for TDD; 90.0% for non-TDD.

Of course, there is the overhead of writing the tests and understanding how to use a unit testing framework. For smaller projects, this might be an excessive overhead, but for most non-trivial projects, test-driven development can still be useful. If you're only developing a few functions, you might only need a few tests, and it's great preparation for industry, where TDD is very common.

So, in short, don't just stress the importance of testing and hope they listen, integrate it into your teaching. If writing good tests is the norm in your class, it's far more likely that rigorous tests will be written.

• "testing is part of the project". Golden. If only the ministry-supplied curriculum thought this way. – ItamarG3 Jun 20 '17 at 16:38
• Yes, testing needs to be seen as integral, important, and authentically valued. Otherwise, it's just another thing for a student to check off the list---and if you're gonna get a good grade anyway, why bother? I tried to teach unit testing in extracurricular support activities, but it didn't stick like I'd hoped. Later, students started working at tech companies and told me, "You should really have taught us unit testing. It's so important!" It's got to be in the curriculum to be effective, imo. – nova Jul 17 '17 at 19:14

The first problem my students always have with this is that they don't even understand how to test their code. They've run the program, and it works. So... it must work.

I have two approaches to this, and while they definitely help, I will also be keeping an eye out on the other answers for more pointers.

• The first is simply to create test-cases together. I have not made as formal a lesson about this as I would like to, but I opportunistically will create tests with the class when we code together on the projector.

Thinking about this now, I would want to create a few methods with some non-obvious flaws (such as breaking on empty lists, odd numbers of items in an array, null entries within an array, negative numbers, etc), and provide .jar files with no source code. Ask students to find the errors, and then reflect together on what kinds of tests were helpful.

• I have one truly awful lab I assign, where I make one student per group of three create an extremely thorough testing class for a larger set of classes coded by their peers. Through some fairly thorough (albeit informal) polling, the students who have to go through that portion of the lab say that they have a much better idea of how to test code (though they do not come out enthusiastic about it.)

One approach could be to use their classmates for assistance.

Assign a project. Explain that each person is going to do the project, and then they will hand the resulting code over to another student (probably randomly assigned). That student will then test the code.

• The writer will get credit for whether or not the code worked correctly.
• The verifier will get credit for correctly identifying whether the code worked or did not.

An interesting variant on this might be to offer extra credit for verification tasks. Students may submit their work early and have their work put in a pile of programs to verify. Students may choose to do verification for extra credit, in which case they are assigned a random program from the pile. To get the extra credit they either need to:

• Declare that the program works, and it in fact works when you (the teacher) test the program.
• You may require some documentation showing how thorough the testing was.
• Document a test case which demonstrates that the program fails which the teacher agrees with.

In the latter case, the program is kicked back to the original writer, along with the results of this Q&A test. The results will probably be a lot of programs where the original writer relies on the verifier to do the testing, but these are also the students who are going to need some extra-credit to make up for their poor scores on the programs, so hopefully they'll try to verifiy some other student's code. If they do, they'll learn the value of testing that way!

I would take Cort Ammon's suggestion a step further.

Cover the ideas behind testing - I show both TDD and what I actually do which is constantly test my code as I develop. Then give a two part project.

Part 1 - the students implement some library of functions/objects etc.

Part 2 - each kid builds something using another kids library.

Kids are graded on how well and well documented their code is for the next person. This encourages thorough testing as well as well written clear code.

• This is a nicely conceived lesson. – Ben I. Jun 20 '17 at 20:40

I think it is important to stress that computers "do what you tell them, not what you think you tell them". From there, testing is a way to see if what you've told them to do is what you think you've told them to do.

I would do this by comparing it to something they understand. At that age group, it could be something completely unrelated to computers. For example, do the Peanut Butter and Jelly Sandwich Experiment where one student writes down how to make a PB&J sandwich and a different student follows those instructions exactly. (the results are usually not a sandwich).

Lastly, I would try to teach testing not as a "thing you do at the end" but something you do along the way. A professional programmer tests their code every few lines. I start my programs as a "Hello, world!" program and I run it just to make sure I have my headers and other boilerplate correct. Then I replace the "Hello, world!" statement with a few lines that implement the basics of the program (maybe just open the file and close it). I then test that. I keep doing these iterations along the way. (A good explanation of this is in The Practice of Programming by Kernighan and Pike.

If your students learn to test after every few lines they'll learn faster, be less frustrated as they code, and gain more satisfaction from coding. They'll learn faster, because they'll get faster feedback. They'll be less frustrated because they won't have dozens (or hundreds?) of errors to deal with at a time. They'll gain more satisfaction because their code will work better.

• I really hate this damned machine / I wish that they would sell it. / It never does quite what I want / But only what I tell it. – Ben I. Jun 21 '17 at 17:19

A good way of doing this is showing them (via example) how important it is.

A small piece of code in a lab period can be used to show them how everything falls apart if you don't test your code. Going by:

Bugs are small beings, so you need to look for them with a magnifying glass.

Testing is the magnifying glass.

Using a piece of code that, at first glance, looks just fine. Show them that for the input it was made for (but not exclusively for that input) the code works smoothly.

However, given some input (which the program should theoretically be able to handle), the code fails miserably. The key point is the should theoretically. It should, but without testing it, it might as well be that it can't.

This example usually shows why it's important to do tests even where no problems should appear. Because, again, bugs are small things that create big problems.

I'd recommend giving them a test suite with their assignments from the beginning. That way, from the start they'll understand that testing code is something that can be done. The more interested students will probably go ahead and look at the test suite and maybe ask questions about it.

When you get to decently large assignments, you can take a day or two and show them how the "grader" (test suite) actually works. Then you can have them write test suites for their own assignments in advance, for example you can write a test suite in class, and tell them that their homework is to made a program that passes those tests.

This way, the students will get a gradual introduction and really see test suites in action for the whole year while they gradually gain a better understand of what's happening "under the hood".

Tell them a story like this, if you build a boat are you going to cross the big sea straight ahead ? What happens then if you have a leak ? That's what big men do to educate, parrables.

How is it important for your students? What does it matter to them now, what does it matter to them in the end?

Some want to be educated, some just want their degree, some want both, and some want none (these one shall be your masters). From these four categories you can make two categories: those that listen to you and those who do not.

For the purpose of stressing out one matter or another, I think you have two ways, you can either repeat it over and over or teach them a lesson once and for all.

It's so hard to find good examples that it's better to use off subjects ones. Do you go on a trip without checking your gas? Are you attacking your enemies without checking your gear?

In the end all of your students will find peace because the ones you think you lost just found another way.

• Welcome to Computer Science Educators! This answer could really benefit from some details on how this teaches students the importance of testing. Could you add some explanation to your answer? – ItamarG3 Jun 20 '17 at 17:03

You could try giving them some problems from competitive programming websites (You can find some very simple problems) which usually give you some sort of test input and also outline the boundaries of which the program must run. Typically in the sample input, they will include test cases that sit near the boundaries of whatever it is you need to solve.

• Would this be the beginning of a class discussion? Or just a way to make sure that they are exposed to some good test cases? How do you bring the lesson home? In any case, welcome to CSE! – Ben I. Jun 20 '17 at 21:20

You could use some examples, like Ariane 5 catastrophe:

The greater horizontal acceleration caused a data conversion from a 64-bit floating point number to a 16-bit signed integer value to overflow and cause a hardware exception. Efficiency considerations had omitted range checks for this particular variable, though conversions of other variables in the code were protected. The exception halted the reference platforms, resulting in the destruction of the flight.

• This is not a good example to showcase testing. That code had been thoroughly tested, but only in an Ariane 4 context. Ariane 5 required extra tests because the conditions in which this code was called had changed, but the change in conditions had not been detected as important. If it had been detected then people would have updated the code. This example showcases formal methods — that crash prompted Ariane to start doing static analysis. – Gilles 'SO- stop being evil' Jun 21 '17 at 9:12

Use a rubric, even for a small assignment, that requires:

• two or three incrementally developed, working versions of code
• one non-working version of code with a explanation of the error and how it was identified.

I distribute starter code with a filename like assignment_6_imageArtist_YourNames_v0 and ask that teams turn in files labelled with the names and v1, v2, and v3 and the non-working version v1.1 or v2.5 for example.