Skip to content

Instantly share code, notes, and snippets.

@antonymarcano
Created August 24, 2012 06:42
Show Gist options
  • Save antonymarcano/3446733 to your computer and use it in GitHub Desktop.
Save antonymarcano/3446733 to your computer and use it in GitHub Desktop.
PostCode exercise (unfinished) in Java

If you were writing a postcode class with basic validation, this is one point you might reach along your journey. This illustrates one approach to removing duplication from a test.

Note that duplication has been minimised in the 'validPostCodes' scenarios. To ensure that failure messages identify the input that has caused the failure, the 'failure reason' argument in assertThat( String reason, T actual, Matcher<T> expected) has been used. Without this 'reason' it would not be apparent which of the input examples caused the test to fail.

This is incomplete and does not support all postcode formats nor does it handle all exception cases.

This example created by @antonymarcano and @jamesmartin

package com.riverglide.addressservice;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
public class PostCode {
private static final String VALID_OUTCODE = "\\d[A-Z][A-Z]";
private static final int OUTCODE_LENGTH = 3;
private String inCode;
private String outCode;
public PostCode(String rawPostCode) {
String postCode = noSpacesIn(upperCase(rawPostCode));
inCode = firstPartOf(postCode);
outCode = secondPartOf(postCode);
ensureThatWeHaveAValid(outCode);
}
public String toString() {
return inCode + " " + outCode;
}
private String noSpacesIn(String rawPostCode) {
return rawPostCode.replaceAll("\\s+", "");
}
private String upperCase(String rawPostCode) {
return rawPostCode.toUpperCase();
}
private String firstPartOf(String postCode) {
return postCode.substring(0, outCodePositionFrom(postCode));
}
private String secondPartOf(String postCode) {
return postCode.substring(outCodePositionFrom(postCode));
}
private int outCodePositionFrom(String postCode) {
return postCode.length() - OUTCODE_LENGTH;
}
private void ensureThatWeHaveAValid(String outCode) {
try {
assertThat(outCode.matches(VALID_OUTCODE), is(true));
}
catch (AssertionError e) {
throw new NotAValidPostCodeComplaint();
}
}
}
package com.riverglide.address.test;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.Arrays;
import java.util.List;
import org.junit.Test;
import com.riverglide.addressservice.NotAValidPostCodeComplaint;
import com.riverglide.addressservice.PostCode;
public class PostCodeTest {
@Test
public void validPostCodes() throws Exception {
List<Example> postCodes = asFollows(
eg("M1 1AA" ).shouldResultIn("M1 1AA"),
eg("m1 1aa" ).shouldResultIn("M1 1AA"),
eg("m11aa" ).shouldResultIn("M1 1AA"),
eg("B33 8TH").shouldResultIn("B33 8TH")
);
for (Example example : postCodes) {
PostCode postCode = new PostCode(input(example));
assertThat(forThis(example),
postCode.toString(), is(expectedOutputFor(example)));
}
}
@Test(expected=NotAValidPostCodeComplaint.class)
public void complainWhenThePostCodeDoesNotHaveAValidOutcode() throws Exception {
new PostCode("A1 AAA");
}
private List<Example> asFollows(Example...postcodes) {
return Arrays.asList(postcodes);
}
private String forThis(Example example) {
return "For: <" + input(example) + ">";
}
private String expectedOutputFor(Example example) {
return example.getExpectedOutput();
}
private String input(Example example) {
return example.getInput();
}
private Example eg(String input) {
return new Example(input);
}
public class Example {
private final String input;
private String expectedOutput;
private Example(String input) {
this.input = input;
}
public Example shouldResultIn(String expectedOutput) {
this.expectedOutput = expectedOutput;
return this;
}
public String getInput() {
return input;
}
public String getExpectedOutput() {
return expectedOutput;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment