Created
January 28, 2016 13:53
-
-
Save michaelbannister/2f752cbd28c3124ff18e to your computer and use it in GitHub Desktop.
String calculator TDD kata first attempt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.regex.Pattern | |
class StringCalculator { | |
def add(String expression) { | |
if (expression.isEmpty()) { | |
return 0 | |
} | |
def delimiter = findCustomDelimiterPattern(expression) | |
expression = stripDelimiterSpecification(expression) | |
rejectNegatives(expression) | |
def sum = 0 | |
for (String string : expression.split(delimiter)) { | |
int number = Integer.parseInt(string) | |
if (number <= 1000) { | |
sum += number | |
} | |
} | |
sum | |
} | |
private void rejectNegatives(String expression) { | |
if (expression.contains('-')) { | |
def negatives = expression.findAll(/-\d+/) | |
throw new NegativesNotAllowedException(negatives.join(',')) | |
} | |
} | |
private String stripDelimiterSpecification(String expression) { | |
if (hasCustomDelimiter(expression)) { | |
expression.split('\n', 2).last() | |
} else { | |
expression | |
} | |
} | |
private String findCustomDelimiterPattern(String expression) { | |
if (!expression.startsWith('//')) { | |
return '[,\n]' | |
} | |
def firstLine = expression.split('\n')[0] | |
def delimiterSpec = firstLine.substring(2) | |
if (delimiterSpec.length() == 1) { | |
return delimiterSpec | |
} | |
def delimiterPatterns = delimiterSpec.findAll(/\[(.+?)\]/) { match, textInsideSquareBrackets -> | |
Pattern.quote(textInsideSquareBrackets) | |
} | |
delimiterPatterns.join('|') | |
} | |
private boolean hasCustomDelimiter(String expression) { | |
expression.startsWith('//') | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import spock.lang.Specification | |
class StringCalculatorSpec extends Specification { | |
def "add of empty string is 0"() { | |
expect: | |
add('') == 0 | |
} | |
def "add of number is itself"() { | |
expect: | |
add('2') == 2 | |
} | |
def "add of two numbers is their sum"() { | |
expect: | |
add('1,2') == 3 | |
} | |
def "add can sum several numbers"() { | |
expect: | |
add('3,5,7,9') == 24 | |
} | |
def "add numbers separated by newlines"() { | |
expect: | |
add('1\n2') == 3 | |
} | |
def "can specify a custom delimiter"() { | |
expect: | |
add('//;\n1;2') == 3 | |
} | |
def "negative number throws exception"() { | |
when: | |
add('-3') | |
then: | |
thrown(NegativesNotAllowedException) | |
} | |
def "negative number anywhere in the input throws exception"() { | |
when: | |
add('1,-3') | |
then: | |
thrown(NegativesNotAllowedException) | |
} | |
def "first negative number is included in the exception message"() { | |
when: | |
add('-3') | |
then: | |
def e = thrown(NegativesNotAllowedException) | |
e.message == '-3' | |
} | |
def "all negative numbers are included in the exception message"() { | |
when: | |
add('1,-2,3,-4') | |
then: | |
def e = thrown(NegativesNotAllowedException) | |
e.message == '-2,-4' | |
} | |
def "numbers larger than 1000 should be ignored"() { | |
expect: | |
add('2,1001,1004,2') == 4 | |
} | |
def "delimiter can be longer than one character"() { | |
expect: | |
add('//[***]\n1***2***3') == 6 | |
} | |
def "custom delimiter may be multiple characters"() { | |
expect: | |
add('//[*][%]\n1*2%3') == 6 | |
} | |
def add(expression) { | |
new StringCalculator().add(expression) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment