CSC/ECE 517 Fall 2012/ch2a 2w11 aa: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 9: Line 9:
Annice
Annice
=Examples=
=Examples=
Danielle
 
==Homework Grades Program==
 
===Setup===
As a simple example, we are creating a program that keeps track of our homework grades. We envision that we would be able to get the average of these homework grades. Step one: <b> write a test </b>. Let's test an average function
 
<pre>
  myHomework = new Homework();
  myHomework.grades = [100, 50];
  assert(myHomework.average(myHomework.grades) == 75);
</pre>
 
We will get multiple errors - this test won't even compile (but, that's ok for now). Let's take a look at what will generate error messages:
 
* class <code>Homework</code> not declared
* <code>Homework</code> constructor not declared
* field <code>grades</code> not declared
* method <code>average</code> not declared
 
Now, we fix the first error:
 
<pre>
class Homework {
 
}
</pre>
 
Second error:
 
<pre>
Homework(void) {
 
}
</pre>
 
Third error:
 
<pre>
int * grades;
</pre>
 
Fourth error:
 
<pre>
int average(int * grades) {
  return 0; // default return value
}
</pre>
 
Finally, the test compiles! The code now looks like this:
 
<pre>
class Homework {
 
  int * grades;
 
  Homework(void) {
 
  }
 
  int average(int * grades) {
 
    return 0; // default return value
}
 
}
</pre>
 
===Red===
Now, we run the test, and the familar red bar of failure greets us (remember the mantra red-green-refactor). The assert fails. The average function needs to actually average something (not just return 0). As we think about averaging the grades, we realize we need to know how many grades are in the int array <code>grades</code>. So, we add to the code:
 
<pre>
class Homework {
 
  int * grades;
  int numGrades;                        // new
 
  Homework(void) {
 
  }
 
  int average(int * grades) {
  int avg = 0;                        // new
  for(int i = 0; i < numGrades; i++) { // new
    avg += grades[i];                  // new
  }                                    // new
  return avg/numGrades;                // new
}
 
}
</pre>
 
Of course, we must remember to change the test to:
 
<pre>
  myHomework = new Homework();
  myHomework.grades = [100, 50];
  myHomework.numGrades = 2;
  assert(myHomework.average(myHomework.grades) == 75);
</pre>
 
===Green===
Success! We have a green bar when we run it.
 
===Refactor===
The last step is refactoring. Perhaps we don't want a grade to be an <code>int</code>? Should it be an <code>unsigned int</code>? For this simple example, there isn't much refactoring to do, but in a larger example there may be multiple areas for improvement.
 
=Conclusion=
=Conclusion=
Danielle
Danielle

Revision as of 15:14, 22 October 2012

Introduction

Test driven development (TDD) is a process that tries to create the minimal amount of code to meet customer's expectations. The idea is to test first, code second, then improve (or refactor) last. This process forces the software developers to focus on customer specifications and validation first. Since at each step of the way the programmer proves to himself that the code meets specifications, TDD gives the programmer confidence. The rest of this chapter gives the motivation for TDD, shows the steps for TDD, outlines the principles of TDD, and provides examples using TDD.

Motivation for TDD

Annice

Steps

Annice

Principles

Annice

Examples

Homework Grades Program

Setup

As a simple example, we are creating a program that keeps track of our homework grades. We envision that we would be able to get the average of these homework grades. Step one: write a test . Let's test an average function

  myHomework = new Homework();
  myHomework.grades = [100, 50];
  assert(myHomework.average(myHomework.grades) == 75);

We will get multiple errors - this test won't even compile (but, that's ok for now). Let's take a look at what will generate error messages:

  • class Homework not declared
  • Homework constructor not declared
  • field grades not declared
  • method average not declared

Now, we fix the first error:

class Homework {

}

Second error:

Homework(void) {

}

Third error:

int * grades;

Fourth error:

int average(int * grades) {
  return 0; // default return value
}

Finally, the test compiles! The code now looks like this:

class Homework {

  int * grades;

  Homework(void) {

  }

  int average(int * grades) {

    return 0; // default return value
 
 }

}

Red

Now, we run the test, and the familar red bar of failure greets us (remember the mantra red-green-refactor). The assert fails. The average function needs to actually average something (not just return 0). As we think about averaging the grades, we realize we need to know how many grades are in the int array grades. So, we add to the code:

class Homework {

  int * grades;
  int numGrades;                         // new

  Homework(void) {

  }

  int average(int * grades) {
 
   int avg = 0;                         // new
 
   for(int i = 0; i < numGrades; i++) { // new
     avg += grades[i];                  // new
   }                                    // new
 
   return avg/numGrades;                // new
 
 }

}

Of course, we must remember to change the test to:

  myHomework = new Homework();
  myHomework.grades = [100, 50];
  myHomework.numGrades = 2;
  assert(myHomework.average(myHomework.grades) == 75);

Green

Success! We have a green bar when we run it.

Refactor

The last step is refactoring. Perhaps we don't want a grade to be an int? Should it be an unsigned int? For this simple example, there isn't much refactoring to do, but in a larger example there may be multiple areas for improvement.

Conclusion

Danielle

References