HW3: Cypherdelic¶
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.
Test Coverage Settings
Please add the following lines to the end of your .vscode/settings.json
file, just before
the closing brace:
"java.test.config": {
"coverage": {
"appendResult": false,
},
},
Learning Objectives¶
- Apply testing and debugging
- Implement black-box/closed-box testing, white-box/open-box testing (and the JUnit framework)
- Develop test coverage (and the EclEmma/JaCoCo framework)
- Demonstrate understanding in 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
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 the PhraseCypher
class are not random. Rather, you should come up (just arbitrarily see definition 1b
, and notice the use of "random" in definition 1a
) with some examples that aren't already covered by the white-box tests or the heuristic tests.
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 submitting to Gradescope, make sure you've checked off each item
☐ 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? -
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¶
Testing Terminology
Black-box testing¶
Definition: Testing that is based on the specification of the code being tested (without insight into the actual implementation).
White-box testing¶
Definition: Testing that is based on the implementation of the code being tested, meaning the test author has access to the source code under test.
Rule of Thumb¶
Definition: A rule of thumb in software testing refers to a practical, experience-based guideline that helps testers make quick decisions without requiring strict theoretical proof. These rules are not absolute but serve as helpful heuristics to identify potential issues efficiently.
Heuristic¶
Definition: Heuristic testing is an approach to software testing that relies on experience-based techniques, practical problem-solving, and best-guess strategies rather than exhaustive testing. It involves using heuristics, rules of thumb or informed approximations, to quickly identify defects or assess software quality.
Random Test¶
Definition: A test with inputs that were chosen at random by the tester, along with the associated expected output.