Выбрать главу

Nothing will give you more peace of mind than thoroughly tested code. If it’s been a hassle for you in the past, use an automated framework, such as the one we’ve presented here, to integrate routine testing into your daily work. You (and your users!) will be glad you did.

Exercises

             1.             Write a test program using the TestSuite Framework for the standard vector class that thoroughly tests the following member functions with a vector of integers: push_back( ) (appends an element to the end of the vector), front( ) (returns the first element in the vector), back( ) (returns the last element in the vector), pop_back( ) (removes the last element without returning it), at( ) (returns the element in a specified index position), and size( ) (returns the number of elements). Be sure to verify that vector::at( ) throws a std::out_of_range exception if the supplied index is out of range.

         14.             Suppose you are asked to develop a class named Rational that supports rational numbers (fractions). The fraction in a Rational object should always be stored in lowest terms, and a denominator of zero is an error. Here is a sample interface for such a Rational class:

class Rational {

public:

   Rational(int numerator = 0, int denominator = 1);

   Rational operator-() const;

   friend Rational operator+(const Rational&,

              const Rational&);

   friend Rational operator-(const Rational&,

              const Rational&);

   friend Rational operator*(const Rational&,

              const Rational&);

   friend Rational operator/(const Rational&,

              const Rational&);

   friend ostream& operator<<(ostream&,

               const Rational&);

   friend istream& operator>>(istream&, Rational&);

   Rational& operator+=(const Rational&);

   Rational& operator-=(const Rational&);

   Rational& operator*=(const Rational&);

   Rational& operator/=(const Rational&);

   friend bool operator<(const Rational&,

          const Rational&);

   friend bool operator>(const Rational&,

          const Rational&);

   friend bool operator<=(const Rational&,

                          const Rational&);

   friend bool operator>=(const Rational&,

           const Rational&);

   friend bool operator==(const Rational&,

           const Rational&);

   friend bool operator!=(const Rational&,

           const Rational&);

};

Write a complete specification for this class, including pre-conditions, post-conditions, and exception specifications.

         15.             Write a test using the TestSuite framework that thoroughly tests all the specifications from the previous exercise, including testing exceptions.

         16.             Implement the Rational class so that all the tests from the previous exercise pass. Use assertions only for invariants.

         17.             The file BuggedSearch.cpp below contains a binary search function that searches the range [beg, end) for what. There are some bugs in the algorithm. Use the trace techniques from this chapter to debug the search function.

// BuggedSearch.cpp

#include "../TestSuite/Test.h"

#include <cstdlib>

#include <ctime>

#include <cassert>

#include <fstream>

using namespace std;

// This function is only one with bugs

int* binarySearch(int* beg, int* end, int what) {

  while(end - beg != 1) {

    if(*beg == what) return beg;

    int mid = (end - beg) / 2;

    if(what <= beg[mid]) end = beg + mid;

    else beg = beg + mid;

  }

  return 0;

}

class BinarySearchTest : public TestSuite::Test {

  enum { sz = 10 };

  int* data;

  int max; //Track largest number

  int current; // Current non-contained number

// Used in notContained()

  // Find the next number not contained in the array

  int notContained() {

    while(data[current] + 1 == data[current + 1])

     current++;

    if(current >= sz) return max + 1;

    int retValue = data[current++] + 1;

    return retValue;

  }

  void setData() {

    data = new int[sz];

    assert(!max);

    // Input values with increments of one.  Leave

    // out some values on both odd and even indexes.

    for(int i = 0; i < sz;

        rand() % 2 == 0 ? max += 1 : max += 2)

      data[i++] = max;

  }

  void testInBound() {

    // Test locations both odd and even

    // not contained and contained

    for(int i = sz; --i >=0;)

      test_(binarySearch(data, data + sz, data[i]));

    for(int i = notContained(); i < max;

                   i = notContained())

      test_(!binarySearch(data, data + sz, i));

  }

  void testOutBounds() {

    // Test lower values

    for(int i = data[0]; --i > data[0] - 100;)

      test_(!binarySearch(data, data + sz, i));

    // Test higher values

    for(int i = data[sz - 1];

        ++i < data[sz -1] + 100;)

      test_(!binarySearch(data, data + sz, i));

  }

public:

  BinarySearchTest() {

    max = current = 0;

  }

  void run() {

    srand(time(0));

    setData();

    testInBound();

    testOutBounds();

    delete [] data;

  }

};

int main() {

  BinarySearchTest t;

  t.run();

  return t.report();

}

Part 2.The Standard C++ Library

Standard C++ not only incorporates all the Standard C libraries (with small additions and changes to support type safety), it also adds libraries of its own. These libraries are far more powerful than those in Standard C; the leverage you get from them is analogous to the leverage you get from changing from C to C++.