RU beehive logo ITEC Department logo
ITEC 120
2007spring
ibarland,
jpittges

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs

lab04b
Unit testing
lab04b

Happy groundhog day! (Or, Happy Imbolc (Saturday night… at 24:05EST)

For today's lab, we'll all follow along together. We'll learn about writing automated test suites, so that after writing a test case once, you can press a single button to run all existing tests.

Warm up: type the following into Java's code pad:

String s = "Hello";
String t = "Hel";      // Hel is the goddess of the underworld.

s.length()             // In code pad, leave off the a semicolon if you expect a result.
t.length()
s.contains("o")
t.contains("o")
s.contains(t)
t.contains(s)
This is something new: Previously, even if we had twenty different PizzaServers (jo, mo, curly, …) it didn't really matter who you asked a question of; they all gave the same answer. But each String has different information inside of it, so different Strings might give different answers to the same question!
We'll see next week, how to create our own different objects might have their own internal state (their own private information).

Unit Testing

Websites often require secure passwords. We'll write a function isSecure, which takes in a String and tells whether or not it's a secure-enough password.

  1. Start a new BlueJ project,
  2. create a skeleton:
    class PasswordExpert {
    
    
    
    
      }
    
  3. Write the comments and contract for a method isSecure. (You don't need to know anything more already mentioned, for this step!)
    /** Check whether a proposed password is to be considered secure.
     * @param  ______ ________________
     * @return ________
     */
    _____ ________( _____ _______ )
    
  4. Although we haven't decided exactly what makes a password secure yet, we can write a “stub” function: go ahead and write a body which has a single (dummy) return statement: return false;. Clearly, this isn't always correct. But, it will let us compile, and at least call the function.
  5. To turn on BlueJ's test-case tool, select Options > Preferences… > Miscellaneous > Show Unit Testing Tools.
    (On Mac, the Preferences… item is under the main BlueJ menu.)
  6. Now right-click on your class: In addition to the options like compile and new PasswordExpert(), there is now an option Create Test Class.
    Choose this option. This will create a khaki “unit-test” class which is attached to your primary class. (We won't edit the test class manually; instead, as we use BlueJ to record tests, BlueJ will put code inside this (currently empty) unit test class.)
  7. Right click on the test class, and select Create Test Method…. Give it a name, testIsSecure. (We might make several test suites, each stressing a certain feature or set-of-features of our program.)

    By convention, each test begins with the four letters test. This begins recording your actions, which can be replayed in the future.

  8. Go ahead and test your method: Create a new PasswordExpert instance, and right-click on the red instance to call isSecure, testing the password "zzh8m4ba" (which seems pretty hard to guess, so we'll consider it secure).

    As we've already seen, BlueJ will return the answer from our function (currently just an uninformative stub function). However there is also something new, since we are recording a test case: we can assert that the result should be equal to true. That is, we get a chance to enter what the expected result is. Always use the equal to assertion. (For doubles, use equal to (float or double). doubles require this special comparison, since we need to allow a small amount of tolerance, to compensate for round-off error.) For

  9. Still recording, run a couple more test cases. We'll say a password is secure if it's six or more characters, and contains the an "8".
  10. After entereing the expected result from a couple of different tests (did you remember to test the empty string?), click to End recording.
  11. Now, whenever you want to run that entire suite of tests, you can click Run Tests. Try it now. Some tests will pass, and some will fail (presuming you've chosen a reasonable set of test cases).
  12. Let's go write the function! it turns out, just as you can ask PizzaServers questions, you can ask Strings questions. One of those is length(). In the code pad, type
    String s = "tralala";
    s.length()    // Remember: In code pad, leave off the semicolon if you expect an answer.
    
    Aha! Revise your isSecure, so that it returns true whenever the password is at least six letters long. (This won't make our code good enough to pass all the test cases, but it should hopefully pass more test cases than before.)
  13. Beside the method length(), there are other String methods; look them over. (The Itec 120 page has a link near the top, “java.lang docs”; from that page you can locate the docs for class String.)
    In particular, to determine if one String contains another, you can call the contains method.
  14. Finish writing isSecure, so that it correctly checks for more than six characters and contains "8", and thus passes all your test cases.
  15. Write a second method makeSecureVersion which takes in a proposed password, and returns a password which is guaranteed to be secure. Write a stub function which compiles (but for now, always does something stupid, like return the string "lala" or return "" or just return the same String as was passed in (regardless of how secure that proposal actually was).
  16. Record a new test suite for your function. The expected output will be as follows:
    If the proposal is already secure, then it simply returns that.
    If not, it returns the proposal appended with "zzz8zzz" (which will make it secure!).

  17. Run your test cases. Your old testIsSecure should still pass, but your new testMakeSecureVersion had better fail, as our stub function doesn't do any actual work yet.
  18. Now write and compile the body of your function.
  19. Run your test cases — this time, both should pass.
  20. Challenge: A better notion of a secure password is that it is six or more characters long, and it contains at least one letter in a-z, and at least on digit in 0-9.
    A String contains a digit if it is of the precise form: 0 or more of any characters, followed by a digit, followed by 0 or more of any characters. This can be expressed by the regular expression ".*[0-9].*". The “.” represents “any character”, and (in regular expressions) “*” means “0 or more repetitions of the previous thing”. So putting those two together, the regular expression ".*" means “0 or more anythings”, which corresponds to any portion of a string at all. The regular expression "[0-9]" means “any one character between 0 and 9”.
    What good is this notion of a regular expression? Well, Strings have a very handy method named match: you hand a String a regular regular expression, and it tells you whether or not it itself matches that regular expression.

Optional
When done with the tutorial, look inside the unit-test file which BlueJ created for you. You will find the actual Java code corresponding to your creating a new object and calling a method and testing against various outcomes.
Other IDEs may not have BlueJ's “record” feature, but they do provide other tools to help you write the unit-testing code you see inside that file.

Here's a different tutorial you can look at, if you like: Unit Testing with BlueJ tutorial.

homeinfoexamslectureslabshws
RecipeLawsliessyntaxjava.lang docsjava.util docs


©2007, Ian Barland, Radford University
Last modified 2007.Aug.27 (Mon)
Please mail any suggestions
(incl. typos, broken links)
to iba�rlandrad�ford.edu
Powered by PLT Scheme