Project 1.3: Unit Tests for EncodingHelper

Due Monday 4/6 @ 10:45am. Do this portion with your partner.

Goals

Overview

I've stubbed out a class called EncodingHelperChar.java for the core back-end capabilities of our EncodingHelper program. Each EncodingHelperChar object represents a single Unicode character, which can be initialized via several constructors. The class also has a collection of methods that (once you implement them in the next phase of the project, not right now) will return various representations of the character. The comments in EncodingHelperChar.java describe the specifications for these methods. Do not change the method signatures.

In this phase of the project, you're going to write a test class, EncodingHelperCharTest. This class is yours to implement as you see fit. It should consist of JUnit test cases, at least one per method (including constructors) in EncodingHelperChar. For some of the methods, you may want to implement multiple tests for various boundary cases; each of these tests belongs in its own method.

Resources

The following three links are just a starting place for learning more about unit-test design, and also about the mechanics of implementing unit tests with JUnit. I'd encourage you to search around for additional resources. If you find anything especially useful, please post it to Piazza so your classmates can benefit too!

In addition, Python could be a really useful tool for you to double-check yourself, in particular Python 3. Python 3 lets you directly enter Unicode codepoints and bytestrings as literals, and convert between them. Here's an example:

> python3
Python 3.4.2
Type "help", "copyright", "credits" or "license" for more information.
>>> # We can enter Unicode codepoints directly into string literals!
>>> s = '\u043d\u0437\u2113\u2113\u00f8\u0631\u0020\u03c9\u0665\u044f\u2113\u03b4'
>>> s
'нзℓℓøر ω٥яℓδ'
>>> s[3:9]
'ℓøر ω٥'
>>> # We can get the bytes encoding any string in UTF-8:
>>> b = bytes(s[3:9], encoding='utf-8')
>>> b
b'\xe2\x84\x93\xc3\xb8\xd8\xb1 \xcf\x89\xd9\xa5'
>>> #   Note that most of the characters took two bytes to encode.  The space
>>> #   character, though, took only one byte, and also is shown as itself
>>> #   (rather than \xNN) when we display the bytestring, because it has a
>>> #   codepoint less than 128.
>>> # We can also enter bytes manually:
>>> b2 = b'\xcf\x89\xd9\xa5\xcf\x89'
>>> # And decode UTF-8 bytes into a Unicode string:
>>> s2 = b2.decode(encoding='utf-8')
>>> s2
'ω٥ω'

Check out the Python documentation for the bytes type, which you make by prefixing a string literal with a b and then specifying each byte as, e.g., \xC7. To make a string by explicitly specifying one or more Unicode codepoints, just put, e.g., \u043d right inside your string literal. You can also copy and paste Unicode strings directly into string literals.You can enter Unicode codepoints directly into string literals by writing \u inside them. The example above demonstrates all of these features.

Step 0: Pick A Main Repository

In the first phase of this project, both you and your partner created repositories on Bitbucket to store your EncodingHelper code. However, for this phase and the rest of Project 1, the two of you should be working with only one Bitbucket repo. (“Repo” is short for “repository”.) So, before anything else, decide together whose repo to use. Let's call the owner of this repo A, and the other partner B.

  1. On A's Bitbucket account, open the EncodingHepler repo. Click on the gear icon on the left side of the window (for settings), select “Access Management”, and add B to the repository with Write permissions.
  2. On B's computer, delete the local repository for EncodingHelper (that is, the EncodingHelper directory that has a .git directory inside it). Don't worry, everything here ought to already be backed up in B's Bitbucket repository, provided that they pushed all their changes!
  3. Again on B's computer, now pull from A's Bitbucket repository.
  4. Now both A and B can work on the same code, making changes and committing them in their own local repositories. When either of you wants to push to the origin repo (the one stored on Bitbucket), just make sure that you pull right before you push. This will pull down any changes made by your partner since the last time you pulled, thereby preventing you from pushing a change that conflicts with something that they've already done.

If you run into any problems with this process, please post to Piazza! VCSs are designed for collaborative work, but they can be difficult when you're first using them. Part of the point here is to give you practice using these new tools, so don't shy away from the challenge!

Step 1: Get Set Up

Install JUnit

  1. Open up Terminal and create a new directory called “junit” somewhere within your homedir (~). I'd suggest just doing mkdir ~/junit.
  2. Go to the JUnit download page.
  3. Follow each of the links in the “Plain-old JAR” section. Download the latest versions of both JUnit and Hamcrest as JAR files (by right-clicking the word “jar” in the “Download” column and selecting “Save As”). Save them both into the junit directory you created before.
  4. Back on the command line, make symlinks to the files you just downloaded, without the version number as part of the name. For example:
    > cd ~/junit
    > ls
    hamcrest-core-1.3.jar  junit-4.12.jar
    > ln -s hamcrest-core-1.3.jar hamcrest-core.jar
    > ln -s junit-4.12.jar junit.jar
    > ls -l
    total 720
    -rw-r-----@ 1 jadrian  jadrian   45024 Apr  2 11:03 hamcrest-core-1.3.jar
    lrwxr-xr-x  1 jadrian  jadrian      21 Apr  2 11:05 hamcrest-core.jar -> hamcrest-core-1.3.jar
    -rw-r-----@ 1 jadrian  jadrian  314932 Apr  2 11:03 junit-4.12.jar
    lrwxr-xr-x  1 jadrian  jadrian      14 Apr  2 11:05 junit.jar -> junit-4.12.jar
    

Create and commit EncodingHelperChar.java

  1. Open IntelliJ, and then open your EncodingHelper project.
  2. Download EncodingHelperChar.java directly into the src subdirectory for your project. (For me, it's EncodingHelper/src/edu/carleton/jadrian). Switch back to IntelliJ. The file should show up, after a short delay, in your IntelliJ project. If any extra dotfiles show up (like ._EncodingHelperChar.java), just delete them.
  3. Add a package statement to the top of that source file, to match the one at the top of Main.java. (Again, mine says package edu.carleton.jadrian;.)

    Other than that one change, it's critical that you do not change any method signatures in EncodingHelperChar.java.

  4. Back on the command line, change into your project directory, and add and commit the new EncodingHelperChar.java file into your Git repository. Go ahead and push it to Bitbucket too.

Set up JUnit in IntelliJ

  1. In IntelliJ, click on File → Settings, pick the Plugins pane, and make sure that the option for JUnit is checked. Then close out of the Settings dialog, saving your changes.
  2. Click on the word EncodingHelperChar in the class signature (where it says public class EncodingHelperChar). Wait a moment, and you should see a little light-bulb icon pop up to the left. Click that, and select “Create Test”.
  3. When it asks whether to “Create test in the same source root”, click OK.
  4. This will automatically create a new file for you, EncodingHelperCharTest.java, pre-populated with test methods for every method in EncodingHelperChar.
  5. In the wizard that pops up, select JUnit 4 as your testing library. It will probably say that it can't find the library in this module, so click Fix and, if necessary, point it to the junit.jar file you downloaded earlier. Click the checkboxes next to all the method names in the bottom pane. Leave everything else at its default value (including the superclass, which should be blank).

Step 2: Write Your Tests!

Now you're ready for the fun part! Write JUnit tests for all your test cases, using the resources listed at the top of the page and whatever else you can find.

Make sure that you commit your test code periodically with Git. In fact, you should make a first commit, just with the empty methods provided by the wizard, before you actually implement any tests.

Remember also that you must have at least one test case per method, including constructors. If you write multiple test cases, they each belong in a separate method of EncodingHelperCharTest. Give them names that describe their purposes; a common idiom is XShouldY, like toUtf8BytesShouldReturnNonEmpty. It's okay for method names, especially of tests, to be really long!

The EncodingHelperChar class should support all codepoints formally defined in Unicode, even those beyond the basic multilingual plane. You can consult the official UnicodeData.txt data file and/or the Unicode tables on Wikipedia to investigate this. Make sure that you test support throughout the Unicode space!

Step 3: Turn It In

Submit your program by committing (and pushing) it to your Bitbucket repository, tagged as phase2_final.

Remember to double-check on Bitbucket that your push worked, and also that the repo is shared with me and the graders!