
이번 Binder 프로젝트를 하면서
같이 백엔드를 하는 팀원과 테스트 코드를 열심히 짜자는 이야기를 했다.
사실 나도 테스트코드를 짜지 않고 구현만 하는 경우가 꽤 많았아서 이번에 좀 열심히 해야겠다는 생각이 들었다.
그래서, 일단 push-pull 하고 무조건 전체 테스트를 다 돌려서 서로 깨지는 부분이 있으면 말해주기로 했다.
그런데, 문제가 생겼다.
다른 팀원의 PC에서는 잘 돌아가는 테스트가 내 PC에서만 자꾸 깨지는 일이 발생했다.
로직상의 문제는 아닌 것으로 판단됐다.
Expecting actual:
[2024-09-13T10:33:35.690900 (java.time.LocalDateTime),
2024-09-13T10:33:35.690900 (java.time.LocalDateTime),
2024-09-13T10:33:35.706932 (java.time.LocalDateTime)]
to contain exactly (and in same order):
[2024-09-13T10:33:35.690900300 (java.time.LocalDateTime),
2024-09-13T10:33:35.706932400 (java.time.LocalDateTime)]
but some elements were not found:
[2024-09-13T10:33:35.690900300 (java.time.LocalDateTime),
2024-09-13T10:33:35.706932400 (java.time.LocalDateTime)]
and others were not expected:
[2024-09-13T10:33:35.690900 (java.time.LocalDateTime),
2024-09-13T10:33:35.690900 (java.time.LocalDateTime),
2024-09-13T10:33:35.706932 (java.time.LocalDateTime)]
테스트 실패 메시지를 확인했다.
자릿수가 맞지 않는다. actual,즉 실제 값과 기대값의 소수점 자리수가 다르다.
자세한 원인을 파악하기 위해서 디버깅을 해봤다.


비교해보면 생성시간이 찍혔을 때는 소수점 자리수가 781148300인데
db에서 조회할 때는 781148로 찍혔다.
예전에도 이런 비슷한 일이 있었다. Double타입으로 좌표를 넣을 때 특정 소수점 자리에서 반올림이 되는 문제였다.
이런 소수점을 통한 테스트가 쉽지 않은 이유인 거 같다...
MySQL에서는 밀리 초기 Fractional Seconds로 불린다. 시간의 정밀도를 보장하기 위한 개념이다. 기본적으로 up to microsencods(6 digits) precision을 해준다. 즉, 6자리숫자까지 보장하는데 이게 의도치 않는 문제를 만들 수 있다.
INSERT INTO `table_t` VALUES (
2
'2016-05-05 23:59:59.999',
3
'2016-05-05 23:59:59.999',
4
'2016-05-05 23:59:59.999',
5
'2016-05-05 23:59:59.999',
6
);
이런식으로 하면

날짜가 반올림 될 수 있다고 한다.
즉, Fractional Seconds를 지정하지 않은 a는 반올림이 되고 지정한 부분은 지정한 수만큼 자리수를 보장해준다.


자바에서는 LocalDateTime을 소수점 9자리까지를 보전해주는 거 같다.
2024-09-13T14:11:12.058996600
이런식으로 소수점 9번쨰짜리까지 뜬다.
CREATE TABLE TYPEA (C1 datetime(5));
INSERT INTO typeA VALUES ('2018-09-08 17:51:04.77777');
INSERT INTO typeA VALUES ('2018-09-08 17:51:04.777777');
INSERT INTO typeA VALUES( '2018-09-08 17:51:04.777773');
실제로 테스트를 해보자.

DB에는 5자리숫자까지만 표시가되고, 그 이후의 숫자는 반올림이 된 것을 알 수 있따.

CREATE TABLE TYPEA (C1 datetime, C2 datetime(6));
INSERT INTO fractest VALUES
('2024-09-13 15:28:03.575733200','2024-09-13 15:28:03.575733200');
그럼 현재 테스트용 DB에 맞춰서 컬럼을 생성해보자.

Fractional Seconds를 설정하지 않으면 소수점이 사라지고 6으로 설정했더니 소수점 6자리까지만 보전이 됐다.
어디서 많이 본 숫자다.

그렇다.... 결국 DB에서 반올림이 된 것이 문제였던 셈.
공식문서를 보면 반올림이 생길 때 어떤 경고나 에러가 발생하지 않는다. SQL 표준을 따르는 방식이라서 그렇다고 한다.