테스트 주도 개발로 계산기를 구현해 보았다. 숫자 2개 만을 계산하는 간단한 계산기이다. 다음에는 숫자를 연속으로 계산하는 계산기를 구현해 볼 것이다.
.0
소숫점 첫째 자리까지 나왔다. 이 소숫점을 없애는게 힘들었다. double형을 String으로 변환하고 format을 써서 뒤에 소숫점을 없애고 출력하는데 성공했다.String.format("%.2f", num1 - num2) = %.2f는 소수점 3째 자리에서 반올림해서 두 번째 자리까지 출력해 준다. %.0f는 첫 째자리에서 반올림 하고 소숫점은 출력되지 않는다.
package calculator;
import calculator.Calculator;
import calculator.CalculatorRunner;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class CalculatorTest {
Calculator cal = new Calculator(); //공통으로 사용하는 객체를 메서드 밖으로 뺏다.
@Test
void 덧셈() {
double result = cal.add(1, 3); //더하기
assertThat(result).isEqualTo(4.0);
}
@Test
void 뺄셈() {
double result = cal.substract(2, 3); //빼기
assertThat(result).isEqualTo(-1);
}
@Test
void 곱셈() {
double result = cal.multiply(2, 3); //곱하기
assertThat(result).isEqualTo(6);
}
@Test
void 나눗셈() {
double result = cal. divide(4, 2); //나누기
assertThat(result).isEqualTo(2);
}
}
package calculator;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.Scanner;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
public class RunningTest {
@Test
void add실행() {
String str = String.valueOf(Calculator.add(1, 2)); // int 값이 double 형으로 자동 변환되어 들어올 경우, add메서드에 의해 계산된 값을 문자열로 만든다.
String result = String.format("%.0f", Double.parseDouble(str)); // 문자열로 만든 값에서 소숫점을 제외시킨다.
Assertions.assertThat(result).isEqualTo("3");
double result1 = Calculator.add(1.5, 0.469);//double형으로 들어온 경우, double형과 int형도 마찬가지
assertThat(result1).isEqualTo(0.97);
str = String.valueOf(Calculator.add(1.8, 1.2)); // double 형으로 들어왔지만 계산했을 때 소수 아래 자리가 0인 경우
result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("3");
}
@Test
void substract실행(){
String str = String.valueOf(Calculator.substract(1, 2));
String result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("-1");
double result1 = Calculator.substract(1.5, 1.2);
assertThat(result1).isEqualTo(0.3);
str = String.valueOf(Calculator.substract(1.8, 0.8));
result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("1");
}
@Test
void multiply실행(){
String str = String.valueOf(Calculator.multiply(1, 2));
String result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("2");
double result1 = Calculator.multiply(1.5, 1.254);
assertThat(result1).isEqualTo(1.88);
str = String.valueOf(Calculator.multiply(1.8, 0)); // 0을 곱했을 때 0이 나오는지 테스트
result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("0");
}
@Test
void devide실행(){
String str = String.valueOf(Calculator.divide(4, 2));
String result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("2");
double result1 = Calculator.divide(1.5, 1.254);
assertThat(result1).isEqualTo(1.20);
str= String.valueOf(Calculator.divide(0, 1)); // 분자가 0일 때 0이 나오는지 테스트
result = String.format("%.0f", Double.parseDouble(str));
Assertions.assertThat(result).isEqualTo("0");
}
@Test
@DisplayName("0으로 나눌때")
void divide0(){ // 0으로 나눌 수 없기 때문에 0이 들어오면 멘트와 함께 랜덤 숫자가 나온다.
double result1 = Calculator.divide(1.5, 0);
assertThat(result1).isEqualTo(-1);
}
}
package calculator;
import java.util.Scanner;
public class CalculatorRunner {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Comments.numberInputComment();//동일한 멘트가 출력되는 코드를 메서드로 출력시킨다.
double first = scanner.nextDouble();
System.out.print("연산 기호를 입력해 주세요 : "); //변하지 않을 코드이기 때문에 따로 리팩토링하지 않았다.
String operator = scanner.next();
operator = OperatorException.correctOperator(scanner, operator); // 연산 기호를 잘못 입력했을 때 다시 재입력하게하는 메서드이다.
Comments.numberInputComment();
double second = scanner.nextDouble();
if (operator.equals("+")) Output.addResult(first, second);//실제 결과를 출력시키는 메서드이다. 최대한 else를 지양한다.
if (operator.equals("-")) Output.substractResult(first, second);
if (operator.equals("*")) Output.multiplyResult(first, second);
if (operator.equals("/")) Output.divideResult(first, second);
}
}
package calculator;
public class Calculator {
public static double add(double num1, double num2) {
String result = String.format("%.2f", num1 + num2); //소수 2번째 자리까지 출력
return Double.parseDouble(result);
}
public static double substract(double num1, double num2) {
String result = String.format("%.2f", num1 - num2);
return Double.parseDouble(result);
}
public static double multiply(double num1, double num2) {
String result = String.format("%.2f", num1 * num2);
return Double.parseDouble(result);
}
public static double divide(double num1, double num2) {
if(num2 == 0){// 나누기기를 수행하는 메서드에서 0으로 나눌수 없다.
System.out.println("0으로 나눌 수 없습니다.");
return Math.random();//0이 인자로 들어왔을 때 난수를 출력한다.
}
String result = String.format("%.2f", num1 / num2);
return Double.parseDouble(result);
}
}
package calculator;
public class Comments {
public static void numberInputComment(){
System.out.print("숫자를 입력해 주세요 : "); //중복으로 사용되는 코드를 메서드로 묶었다.
}
}
package calculator;
import java.util.Scanner;
public class OperatorException {
public static String correctOperator(Scanner scanner, String operator) {// scanner를 사용해서 재입력을 받아야하므로 파라미터로 넣는다., 잘못된 연산자를 파라미터로 넣는다.
while (!(isOperator(operator)) {//만약 사칙연산기호가 아니면 while문을 수행한다.
System.out.println("올바른 연산 기호를 입력해 주세요(+, - , * ,/) : ");
operator = scanner.next();
if (isOperator(operator)) return operator; // 올바른 연산자가 재입력됐을때 while문을 빠져나온다.
}
return operator;// 제대로 입력이 됐다면 그 연산자를 리턴한다.
}
public static boolean isOperator(String operator) { // 올바른 코드를 입력했을 때 반복문을 빠져나올 메서드를 따로 만들었다. while문 안에 있으면 너무 복잡해 진다.
if (operator.equals("+") || operator.equals("-") || operator.equals("*") || operator.equals("/")) {
return true;
}
return false;
}
}
package calculator;
public class Output {
public static void divideResult(double first, double second) {
String result = String.valueOf(Calculator.divide(first, second));
if (result.contains(".0")) {
System.out.println(String.format("%.0f", Double.parseDouble(result))); // return할 것이 없기 때문에 else를 쓸 수 밖에 없다.
} else {
System.out.println(Calculator.divide(first, second));
}
}
public static void addResult(double first, double second) {
String result = String.valueOf(Calculator.add(first, second));
if (result.contains(".0")) {
System.out.println(String.format("%.0f", Double.parseDouble(result)));
} else {
System.out.println(Calculator.add(first, second));
}
}
public static void substractResult(double first, double second) {
String result = String.valueOf(Calculator.substract(first, second));
if (result.contains(".0")) {
System.out.println(String.format("%.0f", Double.parseDouble(result)));
} else {
System.out.println(Calculator.substract(first, second));
}
}
public static void multiplyResult(double first, double second) {
String result = String.valueOf(Calculator.multiply(first, second));
if (result.contains(".0")) {
System.out.println(String.format("%.0f", Double.parseDouble(result)));
} else {
System.out.println(Calculator.multiply(first, second));
}
}
}