질문 역사
SQL의 비즈니스 로직(저장 프로시저, 함수, 트리거 수준) 수동 검사는 생산 환경에서만 드러나는 오류를 초래합니다. 오랫동안 SQL 시나리오 테스트는 비공식적이고 비표준적이었습니다. 그러나 CI/CD 기술의 발전은 SQL 코드에 대한 자동화된 테스트를 요구합니다.
문제
대부분의 개발자는 애플리케이션 레벨의 테스트로만 제한됩니다. SQL 프로시저 및 함수 본체의 검사가 없으면, UDF의 로직 변경이나 보고서의 회귀와 같은 테스트 패키지로 커버되지 않는 결함이 발생합니다.
해결책
현대 팀의 작업 과정에서는 SQL 코드에 대해 단위 및 통합 테스트를 구성합니다. 단위 테스트에는 tSQLt(SQL Server), utPLSQL(Oracle), pgTAP(PostgreSQL)와 같은 프레임워크를 사용하며, 통합 테스트에는 임시 데이터베이스를 설정하고 마이그레이션을 적용하며 비즈니스 시나리오를 검증하기 위한 별도의 환경이 사용됩니다.
pgTAP에서의 단위 테스트 예시:
-- 급여 분리를 확인합니다 SELECT plan(2); SELECT is( (SELECT calc_salary(1)), 1000, '사용자 1의 급여가 정확합니다' ); SELECT isnt( (SELECT calc_salary(2)), 0, '사용자 2의 급여는 0이 아닙니다' ); SELECT finish();
CI/CD를 위한 통합 테스트 코드:
psql -U user -d testdb < migrations.sql psql -U user -d testdb < test_data.sql psql -U user -d testdb -c "SELECT * FROM my_procedure_test();"
주요 사항:
대규모 프로시저일 경우, 애플리케이션 레벨의 자동 테스트만으로 충분합니까? 아니요, UI/API 테스트는 SQL 로직의 정확성을 보장하지 않습니다(예: 저장 함수 내의 잘못된 조건이나 데이터 업데이트 중의 위반). 단위 테스트는 SQL 코드 내에서 모든 루트 분기 실행을 커버해야 합니다.
"수동" 테스트 스크립트 실행만으로 충분합니까? 데이터베이스에서 변경이 적은 경우요? 충분하지 않습니다. 작은 프로젝트에서도 스키마 또는 로직 변경 후 버그가 발생합니다. CI 프로세스에서 테스트 자동화는 인간의 오류를 줄이고 회귀를 방지합니다.
"중요한" 프로시저만 테스트하고 나머지는 생략할 수 있습니까? 최선의 접근 방식은 가능한 많은 기능을 포함하는 것입니다. 특히 여러 팀이 코드를 변경할 경우, 비공식적인 계산 및 엣지 케이스는 종종 비표준 분기에서 드러납니다.
할인 계산 프로시저를 개선하는 동안 손으로 몇 가지 케이스를 테스트했지만 주요 논리 경로를 놓쳤습니다. 생산 환경에서 고객이 잘못된 할인을 받기 시작했고, 해결하는 데 며칠이 걸렸습니다.
장점:
초기 시간 절약.
단점:
수동 수정으로 인한 손실, 개선 및 리팩토링 시 불편함.
모든 주요 UDF 및 프로시저에 대해 pgTAP로 단위 테스트를 개발하고, 통합 테스트는 브랜치 병합 시마다 CI를 통해 수행됩니다. 오류 및 회귀는 배포 전에 발견됩니다.
장점:
기능의 안정성, 비즈니스 로직을 신속하게 개선할 수 있는 가능성, 생산 환경의 최소한의 버그.
단점:
테스트 기반을 시작하고 유지하기 위한 시간 투자 필요.