diff --git a/requirements.txt b/requirements.txt index 706a953..271d52a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,4 +17,5 @@ langchain-google-genai>=2.1.3,<3.0.0 langchain-ollama>=0.3.2,<0.4.0 langchain-huggingface>=0.1.2,<0.2.0 clickhouse_driver -numpy<2.0 \ No newline at end of file +numpy<2.0 +pytest>=8.3.5 diff --git a/setup.py b/setup.py index 78f0612..9313df4 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ # setup.py -from setuptools import setup, find_packages +from setuptools import find_packages, setup with open("docs/README.md", "r", encoding="utf-8") as fh: long_description = fh.read() @@ -29,6 +29,7 @@ "langchain-ollama>=0.3.2,<0.4.0", "langchain-huggingface>=0.1.2,<0.2.0", "transformers==4.51.2", + "pytest>=8.3.5", ], entry_points={ "console_scripts": [ diff --git a/test/test_llm_utils/test_llm_response_parser.py b/test/test_llm_utils/test_llm_response_parser.py new file mode 100644 index 0000000..15f215d --- /dev/null +++ b/test/test_llm_utils/test_llm_response_parser.py @@ -0,0 +1,107 @@ +""" +LLMResponseParser 클래스의 기능을 테스트하는 단위 테스트 모듈입니다. + +주요 테스트 항목: +- 블록에서 SQL 쿼리 추출 성공/실패 +- <해석> 블록에서 자연어 설명 추출 성공/실패 +- 다양한 입력 형식(들여쓰기, 공백 등)에 대한 정규식 대응 여부 확인 +""" + +import unittest + +from llm_utils.llm_response_parser import LLMResponseParser + + +class TestLLMResponseParser(unittest.TestCase): + """ + LLMResponseParser 클래스의 정적 메서드 동작을 검증하는 테스트 케이스입니다. + + 각 테스트는 SQL 및 해석 블록 추출 기능이 정상적으로 작동하는지, + 예외 상황에 올바르게 대응하는지를 검증합니다. + """ + + def test_extract_sql_success(self): + """ + 블록과 ```sql``` 코드 블록이 정상적으로 포함된 문자열에서 + SQL 쿼리가 정확히 추출되는지 확인합니다. + """ + + text = """ + + ```sql + SELECT * FROM users; + ```` + + <해석> + + ```plaintext + 사용자 테이블의 모든 데이터를 조회합니다. + ``` + + """ + expected_sql = "SELECT * FROM users;" + result = LLMResponseParser.extract_sql(text) + self.assertEqual(result, expected_sql) + + def test_extract_sql_missing(self): + """ + 블록은 존재하지만 코드 블록이 없을 경우, + ValueError 예외가 발생하는지 확인합니다. + """ + + text = " no code block here" + with self.assertRaises(ValueError): + LLMResponseParser.extract_sql(text) + + def test_extract_interpretation_success(self): + """ + <해석> 블록과 ```plaintext``` 코드 블록이 포함된 문자열에서 + 해석 텍스트가 정상적으로 추출되는지 확인합니다. + """ + + text = """ + ``` + + + ```sql + SELECT * FROM users; + ``` + <해석> + ```plaintext + 사용자 테이블의 모든 데이터를 조회합니다. + ``` + """ + expected = "사용자 테이블의 모든 데이터를 조회합니다." + result = LLMResponseParser.extract_interpretation(text) + self.assertEqual(result, expected) + + def test_extract_interpretation_empty(self): + """ + <해석> 태그는 존재하지만 코드 블록이 없는 경우, + 빈 문자열을 반환하는지 확인합니다. + """ + + text = "<해석> 블록이 없습니다." + result = LLMResponseParser.extract_interpretation(text) + self.assertEqual(result, "") + + def test_extract_sql_with_leading_whitespace(self): + """ + 블록이 들여쓰기되어 있는 경우에도 SQL 쿼리를 정확히 추출하는지 확인합니다. + """ + + text = """ + ``` + + + ```sql + SELECT id FROM orders; + ``` + <해석> + ```plaintext + 주문 테이블에서 ID 조회 + ``` + """ + expected = "SELECT id FROM orders;" + result = LLMResponseParser.extract_sql(text) + self.assertEqual(result, expected.strip())