HW4: Cypherdelic
9 minute read
Homework 4
🛑 To Know Before You Start
As discussed below, on this assignment you may submit to Gradescope at most ten times. Hence, you should be confident that your code is correct before you submit the first time.Learning Objectives
This homework assignment is designed to help you understand unit testing and debugging. This includes an understanding of black-box/closed-box testing, white-box/open-box testing (and the JUnit framework), test coverage (and the EclEmma/JaCoCo framework), the debugging process, and instrumentation techniques.
Overview
The (fictitious) company Cypherdelic has written a PhraseCypher
class that can be used to encrypt and decrypt messages using a secret
key phrase. They have also written a suite of white box tests that
covers all statements and branches in this class. They have come to
you to do additional testing to debug the PhraseCypher
class if
necessary. (Hint: It will be necessary to debug the PhraseCypher
class. In other words, it does contain defects.)
Existing Classes
They have provided you with an implementation of the PhraseCypher
class and a white box test suite (written in Java using the JUnit
framework) that covers all statements and branches in the
PhraseCypher
class.
Some of the specifications for the PhraseCypher
class are
illustrated in the following UML class diagram:
The remaining specifications are included in the comments for the class.
Your Tasks
You must test and debug the PhraseCypher
class that you have been
given. The end result must be a correct version of the PhraseCypher
class with every change you make documented in the
comments. Specifically, you must:
- Create a class named
HeuristicTests.java
that contains JUnit tests based on “rules of thumb” about the inputs for all of the methods in thePhraseCypher
class. - Create a class named
RandomTests.java
that contains JUnit tests based on random inputs for all of the methods in thePhraseCypher
class.⚠️ Note: posted 9/29@12:40PM
The use of the word “random” here is a bit of a misnomer (it was intentional to try to make of use of more colloquial language in an attempt to make it easier to comprehend the spec). The inputs to the methods in thePhraseCypher
class are not random. Rather, you should come up (just arbitrarily see definition1b
, and notice the use of “random” in definition1a
) with some examples that aren’t already covered by the white-box tests or the heuristic tests. If you are on your way down some kind of rabbit hole that has to do with “randomg number generators or the like, 🛑 stop! Make a u-turn ↪️ 😆.
Both classes must have at least four methods. These methods
must be preceded by the JUnit @Test
annotation and must have names
that begin with each of the following:
charOfTest
valueOfTest
decryptTest
encryptTest
(They can have suffixes like charOfTest1()
,
charOfTest2()
, etc. if you would like to have more than four in
total). You should add these methods one at a time, running all of the
tests on your machine each time you do so. Obviously, you should
not submit to Gradescope until you are confident that HeuristicTests.java
and
RandomTests.java
are correct.
When the actual output of one of your tests does not equal the expected output you should understand the symptom and the trigger condition (i.e., stabilize the fault). Then, localize the fault, correct the fault (documenting the correction in the source code), and verify the correction.
Some Likely Rules of Thumb
There are a variety of rules of thumb that people use when testing code.
The Explicit Value Constructor
The explicit value constructor must be passed a String
that contains
all of the letters in ALPHABET
. Some obvious parameters to pass
include:
- A
String
that is missing one letter - A
String
that is identical toALPHABET
- A
String
that is identical toALPHABET
with the characters in reverse - A
String
that is missing the first letter (i.e., the' '
character) - A
String
that is missing the last letter in lower-case (i.e., the'z'
character) - A
String
that is missing the last letter in upper case (i.e., the'Z'
character) - A
String
that contains no letters
You should be able to think of other rules-of-thumb that might be
likely to uncover defects in a method that is passed a String
.
The charOf()
Method
The charOf()
method is passed an int
that is supposed to
correspond to a char
in ALPHABET
. Some obvious parameters to pass
include:
- 0
- 1
- The length of
ALPHABET
- One less than the length of
ALPHABET
- A negative number
- A large number
You should be able to think of other rules-of-thumb that might be
likely to uncover defects in a method that is passed an int
.
The valueOf()
Method
The valueOf()
method is passed a char
that is in ALPHABET
. Some
obvious parameters to pass include:
- The 0th
char
inALPHABET
- The 1st
char
inALPHABET
- The next to last
char
inALPHABET
- The last
char
inALPHABET
- A
char
not inALPHABET
You should be able to think of other rules-of-thumb that might be
likely to uncover defects in a method that is passed a char
.
The encrypt()
Method
The encrypt()
method is passed a String
that contains some or all
of the characters in ALPHABET
. Some obvious parameters to pass
include:
- A
String
that contains all of the letters inALPHABET
- A
String
that is identical toALPHABET
- A
String
that is identical toALPHABET
with the characters in reverse - An upper-case
String
- A lower-case
String
- A mixed-case
String
- A short
String
- A long
String
that contains some letters more than once - A
String
that contains achar
that isn’t inALPHABET
- A
String
that contains multiplechar
s that aren’t inALPHABET
You should be able to think of other rules-of-thumb that might be
likely to uncover defects in a method that is passed a String
.
The decrypt()
Method
The decrypt()
method is passed an int[]
that contains the indexes
of some or all of the characters in ALPHABET
. Some obvious
parameters to pass include:
- An array with 1 element
- A long array
- An array in which all of the elements are the same
- An array sorted in ascending order
- An array sorted in descending order
- An array containing zeroes
You should be able to think of other rules-of-thumb that might be
likely to uncover defects in a method that is passed an int[]
.
Before Submission
Before you submit your code to Gradescope for the first time you should be able to check-off each of the following items.
☐ PhraseCypher.java
has no style defects
☐ The PhraseCypher
constructor throws an IllegalArgumentException
as specified
☐ The decrypt()
method returns the empty String
as specified
☐ The encrypt()
method returns an array of length 0 as specified
☐ HeuristicTests.java
has a charOfTest()
method
☐ HeuristicTests.java
has a valueOfTest()
method
☐ HeuristicTests.java
has a decryptTest()
method
☐ HeuristicTests.java
has an encryptTest()
method
☐ RandomTests.java
has a charOfTest()
method
☐ RandomTests.java
has a valueOfTest()
method
☐ RandomTests.java
has a decryptTest()
method
☐ RandomTests.java
has an encryptTest()
method
Note that if your submission does not include all of the required tests it will fail the Official Tests (not the Self Tests), and you will not receive any hints that indicate this. Hence, it is very important that you manually ensure that your submission is correct.
Submission
You must submit (using Gradescope):
- Your corrected implementation of the
PhraseCypher
class (with appropriate comments). - Your
RandomTests.java
andHeuristicTests.java
.
Because you should not be using Gradescope to verify your code (i.e., because you must be able to test and debug code without the help of a submission system), you may submit to Gradescope at most ten times and you will not receive any hints about the official tests from Gradescope.
Note that your test classes do not need to comply with the style guide.
Grading
Your code will first be graded by Gradescope and then by the Professor. The grade you receive from Gradescope is the maximum grade that you can receive on the assignment
Gradescope Grading
Your code must compile (in Gradescope, this will be indicated in the section on “Does your code compile?”) and all class names and method signatures must comply with the specifications (in Gradescope, this will be indicated in the section on “Do your class names, method signatures, etc. comply with the specifications?”) for you to receive any points on this assignment. Gradescope will then grade your submission as follows:
Criterion | Points | Details |
---|---|---|
Conformance to the Style Guide (Style) | 0 points | (All or Nothing; Success Required) |
Passing Your Tests (SelfTests) | 20 points | (All or Nothing; Success Required) |
Correctness (Official Tests) | 80 points | (Partial Credit Possible) |
As discussed above, you may submit to Gradescope at most ten times. The grade on your last allowed submission will be the grade you receive from Gradescope.
If your submission does not contain all of the required tests, you will receive a 0 for correctness.
Manual Grading
After the due date, the Professor may manually review your code. At this time, points may be deducted for inelegant code, inappropriate variable names, bad comments, etc.
Questions to Think About
You don’t have to submit your answers to these questions, but you should try to answer them because they will help you determine whether or not you understand some of the important concepts covered in this assignment.
- The assignment does not require that your tests completely cover the code. Why not?
- The white-box tests completely covered the code. How could the code still contain defects?
- Why are both heuristic tests (based on rules of thumb) and random tests necessary (in addition to white-box tests)?
- As you know, applications written in Java must have a main class that contains a method with the signature
public static void main(String[])
that is called the entry point of the application. When you write JUnit tests, you do not need to create such a class. What must the JUnit framework be providing behind the scenes? With this in mind, why does Eclipse differentiate betweenRun Configurations
for Java applications and JUnit tests? - How does your answer to the previous question make it a little more convenient to use JUnit than the
Test
class you have used on previous assignments? - JUnit contains
assertEquals()
methods that are passed twoint
values, twodouble
values, twoString
values, etc. What term is used to describe methods that have the same name but different formal parameters? - When a JUnit test fails, an exception is thrown. What happens if the code you are testing throws an exception for other reasons?
Vocabulary
- black-box testing
- Testing that is based on the specification of the code being tested (without insight into the actual implementation).
- white-box testing
- Testing that is based on the implementation of the code being tested, i.e. the test author has access to the source code under test.
- heuristic
- Describing something that is an acceptable approximation, compromising some completeness or perfection for practicality. Often heuristics are informed from (past) empirical observations. ([more on wikipedia](https://en.wikipedia.org/wiki/Heuristic))
- rule of thumb
- Guideline, informed by past experience. Anachronistically associated with jurisdictional tolerance of domestic violence. ([more on wikipedia](https://en.wikipedia.org/wiki/Rule_of_thumb#Folk_etymology))
- random test
- A test with inputs that were chosen at random by the tester (along with the associated expected output)