Functional Problem Solving (CSC 151 2014F) : Labs
Primary: [Front Door] [Schedule] - [Academic Honesty] [Disabilities] [Email] - [FAQ] [Teaching & Learning] [Grading] [Rubric] - [Calendar]
Current: [Assignment] [EBoard] [Lab] [Outline] [Reading]
Sections: [Assignments] [EBoards] [Examples] [Handouts] [Labs] [Outlines] [Readings]
Reference: [Setup] [VM] [Errors] - [Functions A-Z] [Functions By Topic] - [Racket] [Scheme Report (R5RS)] [R6RS] [TSPL4]
Related Courses: [Davis (2013F)] [Rebelsky (2014S)] [Weinman (2014F)]
Misc: [Submit Questions] - [SamR] [Glimmer Labs] [CS@Grinnell] [Grinnell] - [Issue Tracker (Course)]
Summary: In the laboratory, you will explore the ways in which small tests can help you develop and update code. You will also familiarize yourself with our testing library.
a. Open a terminal window and type the following. The instruction tells Racket where to find some of the code for today's lab.
/opt/racket/bin/raco link /home/rebelsky/Web/Courses/CSC151/triangles
b. After starting DrRacket, add (require rackunit) and
(require rackunit/text-ui) to your definitions pane and
click .
Consider the following procedure documentation:
;;; Procedure: ;;; classify-triangle ;;; Parameters: ;;; side1, a rational number [unverified] ;;; side2, a rational number [unverified] ;;; side3, a rational number [unverified] ;;; Purpose: ;;; Determine the kind of triangle the three sides describe. ;;; Produces: ;;; classification, a string ;;; Preconditions: ;;; side1, side2, and side3 together describe a triangle [verified] ;;; Postconditions: ;;; If all three sides are equal, classification is "equilateral". ;;; If exactly two sides are equal, classification is "isosceles". ;;; If no two sides are equal, classification is "scalene".
a. Write a series of tests for this procedure. Your tests should look something like the following:
(require triangles/tri-0000)
(define triangle-tests
(test-suite
"Testing classify-triangle"
(test-case "unit side length equilateral triangle"
(check-equal? (classify-triangle 1 1 1) "equilateral"))))
(run-tests triangle-tests)
b. There are approximately 40 different versions of the procedure of
varying degrees of correctness. (Professor Rebelsky wrote a program
to create them!) They are named as follows (and you can access them
the same way as you accessed tri-0000, provided you use
the raco link command in the preliminaries):
triangles/tri-0000,
triangles/tri-0001,
triangles/tri-0010,
triangles/tri-0011,
triangles/tri-0100,
triangles/tri-0101,
triangles/tri-0110,
triangles/tri-0111,
triangles/tri-0200,
triangles/tri-0201,
triangles/tri-0210,
triangles/tri-0211,
triangles/tri-1000,
triangles/tri-1001,
triangles/tri-1010,
triangles/tri-1011,
triangles/tri-1100,
triangles/tri-1101,
triangles/tri-1110,
triangles/tri-1111,
triangles/tri-1200,
triangles/tri-1201,
triangles/tri-1210,
triangles/tri-1211,
triangles/tri-2000,
triangles/tri-2001,
triangles/tri-2010,
triangles/tri-2011,
triangles/tri-2100,
triangles/tri-2101,
triangles/tri-2110,
triangles/tri-2111,
triangles/tri-2200,
triangles/tri-2201,
triangles/tri-2210, and
triangles/tri-2211
Pick eight or so of those files and run your tests on them. Which ones pass your tests? (Try to collaborate with your classmates so that all of them get tested.)
Here is a test that someone might write for the procedure described above.
(define triangle-tests
(test-suite "Tests of classify-triangle"
(test-case "unit side length equilateral triangle"
(check-equal? (classify-triangle 1 1 1) "equilateral"))
(test-case "simple isosceles triangle"
(check-equal? (classify-triangle 2 2 3) "isosceles"))
(test-case "simple scalene triangle"
(check-equal? (classify-triangle 3 4 5) "scalene"))))
(run-tests triangle-tests)
a. Run this test suite on five of the variants mentioned in problem 2 that you have either not tested or that have passed all tests so far. How many pass the new test suite?
b. Can you envision an obvious solution to
classify-triangle that passes all of these tests,
but fails to meet the specifications? What approach might someone use?
Someone thinking carefully about the definition of
classify-triangle might worry that the tests,
as written, do not check for non-triangles. For example, something
with side lengths 1, 1, and 3 is not a triangle.
So, what should our procedure do when given invalid inputs? It should report an error.
>(classify-triangle 1 1 3)classify-triangle: sides do not describe a triangle
How do we test to see if an error occurs? With the cryptic and
complicated check-exn. Here's the general form.
(check-exn exn:fail? (lambda () *expression-to-test*))
So, for our test about whether or not classify-triangle
fails on inputs of 1, 1, and 3, we might write
(check-exn exn:fail? (lambda () (classify-triangle 1 1 3)))
This says (approximately)
Run (classify-triangle 1 1 3). If it reports
an error, do nothing. If it succeeds, report that it failed to produce
the expected error.
a. Add the check above to your testing code.
b. Run this test suite on five of the variants mentioned in Exercise 2 that you have either not tested or that have passed all tests so far. How many pass the new test suite?
c. Consider the following test. What result do you expect it to have?
>(check-exn exn:fail? (lambda () (classify-triangle 2 2 2)))
d. Check your answer experimentally.
e. Consider the following test. What result do you expect it to have?
>(check-exn exn:fail? (lambda () (classify-triangle 1 1 1 1)))
f. Check your answer experimentally.
Another set of inputs for which classify-triangle
is supposed to fail is one in which any of the side lengths are
negative.
a. Add tests to the test suite
for classify-triangle to ensure
that classify-triangle rejects any set of three
numbers that include a zero or negative number.
b. Run this test suite on five of the variants mentioned in Exercise 2 that you have either not tested or that have passed all tests so far. How many pass the new test suite?
We've tested for each of the three kinds of triangles, but we've only one test for each. What if the programmer mistakenly forgets to deal with the different orderings of parameters? We should make sure that the implementation works for each.
a. Add tests to the test suite for classify-triangle to
ensure that classify-triangle correctly identifies the
three kinds of triangles, not matter what the ordering. In
particular, make sure that you test for the three variants of
isosceles triangles.
(test-case "a few isosceles triangles"
(check-equal? (classify-triangle 2 2 3) "isosceles")
(check-equal? (classify-triangle 2 3 2) "isosceles")
(check-equal? (classify-triangle 3 2 2) "isosceles"))
b. Are there other tests in which the ordering might matter? (Hint: Think about some of the tests for errors.)
c. Run this test suite on five of the variants mentioned in problem 2 that you have either not tested or that have passed all tests so far. How many pass the new test suite?
We now might consider the range of side values for
which classify-triangle should be tested.
a. Add tests that ensure that classify-triangle
works for very large numbers (say, numbers greater than 10 billion).
b. Run this test suite on five of the variants mentioned in problem 2 that you have either not tested or that have passed all tests so far. How many pass the new test suite?
a. Add any other tests you conceive of.
b. Be prepared to discuss those tests in class.
c. Run these tests on any variants mentioned in problem 2 that you have not yet tested or that have passed all the tests up through exercise 9. How many pass the tests?