Programming Task 2


Time Estimate: 5 hours

Jump to current week
Requirements

Project Structure


You will continue to add functionality to your existing project from the previous task. There is no new repository to clone.



Specification


In this task, you will test and implement the following specs:

Note: All methods are public and non-static, unless otherwise noted, from this point forward in the course.

  • ratings.Song - In the ratings package, a class named Song
    • This class will have a constructor that takes 3 parameters in this order:
      1. A String representing the title of the Song
      2. A String representing the artist of the Song
      3. A String representing the Songs ID
    • Song will have getter and setter methods for the three constructor parameters named:
      1. getTitle
      2. setTitle
      3. getArtist
      4. setArtist
      5. getSongID <-- Note that both characters in ID are capital
      6. setSongID
    • For this task, you don't need to implement any additional methods in the Song class (We will add to this class in later tasks)
  • ratings.Rating - In the ratings package, a class named Rating
    • This class will have a constructor that takes 2 parameters in this order:
      1. A String representing the ID of the reviewer who gave the rating
      2. An int representing the rating that the reviewer gave
    • Rating will have getter and setter methods for the two constructor parameters named:
      1. getReviewerID
      2. setReviewerID
      3. getRating
      4. setRating
    • Ratings must be in the range 1-5. If someone calls setRatings with an invalid rating, the rating should be set to -1 to indicate that an error has occurred. (eg. setRating(100) should result in the rating being set to -1). This check must also apply when the constructor is called with an invalid rating.
  • ratings.Reviewer - In the ratings package, a class named Reviewer
    • This class will have a constructor that takes 1 parameter:
      1. A String representing the ID of the reviewer
    • Reviewer will have getter and setter methods for the constructor parameter named:
      1. getReviewerID
      2. setReviewerID
    • rateSong - Reviewer will have a method named rateSong that takes an int as a parameter and returns a reference to a new Rating object (Using the Rating class described above) with this reviewer's ID and the rating from the parameter of this method.

Note: You can see feedback in Autolab for your testing utilities and tests without completing the programming portion of this task, but you must at least create the classes and methods that you test. You can "stub out" these methods by having them always return a fixed value, but they must exist so the grading code, and your tests, can compile and run.



Testing Utilities


To help you write your tests, you will write several testing utility methods. These methods are meant to help you write your unit tests. These methods will compare Song, Rating, and Reviewer objects for equality. When writing test cases, you should create an object with the values that you expect, call the method to be tested to create an object of the same type, then call your utility method to check if the 2 objects contain all the same values.

Create a class named TestClasses1 in the tests package (tests.TestClasses1) and write the following methods in that class (Note: Do not add the @Test annotation to these methods since they are not tests):

  • compareSongs - Write a method named compareSongs in the tests.TestClasses1 class that:
    • Takes [references to] 2 Song objects as parameters
    • Returns a boolean that is true if the title, artist, and id of both Songs are exactly the same. The method either returns false, or fails a JUnit assert, if the Songs do not have all the same values
    • If the 2 Songs do not have all the same values you can either: return false, or have an assert that fails. This gives you the option of using assertTrue, assertEquals, etc. in your utility methods instead of returning false when the test should fail. It is recommended that you write this method with assert statements, then add "return true" as the last line of the method. The method will never return false, but if any assert fails the test will fail without reaching your "return true" line. If you chose to not use asserts and instead return false when the Songs are not identical, be sure to add assertTrue in your test cases when you call this method. (This structure is the same for all utility methods)
  • compareRatings - Write a method named compareRatings in the tests.TestClasses1 class that
    • Takes [references to] 2 Rating objects
    • Returns a boolean that is true if the rating and reviewerID of both Ratings are exactly the same. The method either returns false, or fails a JUnit assert, if the Ratings do not have all the same values
  • compareReviewers - Write a method named compareReviewers in the tests.TestClasses1 class that
    • Takes [references to] 2 Reviewer objects
    • Returns a boolean that is true if the reviewerID of both Reviewers are exactly the same. The method either returns false, or fails a JUnit assert, if the Reviewers do not have the same reviewerID


Testing Requirements


Add test methods to the tests.TestClasses1 class, using the @Test annotation, that tests all the methods in the Specification section. You should call your testing utility methods to save time while writing these tests.



Programming Requirements


Implement the Song, Rating, and Reviewer classes with all the functionality from the specification. As you're writing this code, you should run your tests to see how you are progressing. It's recommended that you write your tests first, submit to Autolab to make sure your have good testing, then use those verified tests to check your code.



Autolab Feedback


The feedback in Autolab will be given in 4 phases. If you don't complete a phase, then feedback for the following phase(s) will not be provided.

  1. Testing your testing utility methods
    • Each of your testing utility methods will be checked with a variety of test cases to ensure that they make all the required checks. This phase will ensure that your utility methods are accurate before you start using them in your tests
  2. Running your tests on a correct solution
    • Your tests will be run against a solution that is known to be correct. If your tests do not pass this correct solution, there is an error somewhere in your tests that must be fixed before you can move on with the assignment. If your tests don't get past this check, you should re-read this document and make sure you implemented your tests and code according the specification. You should also make sure that if there are multiple correct outputs to the input in your tests cases that you accept any of the outputs as correct
  3. Checking your tests for feature coverage
    • The next phase is to check if your tests check for a variety of features defined by different inputs. You should write at least one test case for each feature to pass this phase
    • Passing this phase does not necessarily mean that your testing is completely thorough. Satisfying Autolab is the bare minimum testing requirement. Not all possible inputs are checked, and it is sometimes possible to pass this phase with weak testing. If you are struggling to earn credit for code that you believe is correct, you should write more than the required tests
  4. Running my tests on your solution
    • Once Autolab is happy with your tests, it will run my tests against your code to check it for correctness. If your testing is thorough, and your code passes your tests, then you should pass this phase. If you pass your tests, but fail one of mine, it is an indicator that you should write more tests to help expose your bug

Once you complete all 4 phases, you will have completed this Task and Autolab will confirm this with a score of 1.0 for complete.