
    %<i-                        U d Z ddlZddlZddlZddlmZ ddlZej                  j                  dd       ddl	m
Z
mZ dZg dZee   ed<   g d	Zee   ed
<    ej$                  d      Z ej$                  d      Zd"dededefdZ ej.                  d      defd       Z ej.                  d      dedeeef   fd       Z G d d      Z G d d      Z G d d      Z G d d      Z G d d      Z  G d  d!      Z!y)#u   
test_comparison.py - opendataloader-pdf 파싱 품질 검증 테스트

목적: opendataloader-pdf를 통한 PDF 파싱 품질 데이터 수집.
     키워드 존재, 조항 번호 감지, 특수문자 처리 등을 확인한다.
    N)Anyz/home/jay/workspace/libs)ParseResult	parse_pdfuj   /home/jay/.cokacdir/workspace/autoset/금융소비자_보호에_관한_법률법률제21065호20260102.pdf)u   금융소비자u   금융상품u   금융상품판매업자u   손해배상u   청약철회REQUIRED_KEYWORDS)   「   」u   ㆍ   ·u   ①u   ②u   ③SPECIAL_CHARSu   제\s*\d+\s*조u*   [①②③④⑤⑥⑦⑧⑨⑩]|\b\d+\.\scharwidthreturnc                     | |z  S )N )r   r   s     K/home/jay/workspace/.worktrees/task-2057-dev2/libs/tests/test_comparison.py
_separatorr   4   s    %<    module)scopec                  n    t        t        d      5 } | j                         cddd       S # 1 sw Y   yxY w)uP   테스트 PDF 파일을 바이트로 읽어 반환한다 (모듈 범위 캐싱).rbN)openPDF_PATHread)fs    r   	pdf_bytesr   =   s.     
h	 vvx  s   +4r   c                 x    t        j                         }t        |       }t        j                         |z
  }||dS )u   opendataloader-pdf(parse_pdf) 파싱 결과를 캐싱한다.

    Returns:
        {
            "parse_result": ParseResult,
            "elapsed": float,  # 초 단위
        }
    )parse_resultelapsed)timeperf_counterr   )r   t0resultr   s       r   
odl_resultr#   D   sA     
			B#I.F!B&G  r   c                   x    e Zd ZdZdeeef   ddfdZdeeef   ddfdZdeeef   ddfdZ	deeef   ddfdZ
y)	TestTextExtractionAccuracyu%   항목 1: 텍스트 추출 정확도.r#   r   Nc                 L    |d   j                   }t        |      dkD  sJ d       y)u+   추출된 텍스트가 비어있지 않다.r   r   u*   opendataloader: 텍스트가 비어 있음N)textlen)selfr#   dl_texts      r   test_text_not_emptyz.TestTextExtractionAccuracy.test_text_not_empty`   s*    !.1667|aM!MMr   c                    |d   j                   }t                t        t        d             t        d       t        t                      t        D ]  }||v }|rdnd}t        d|dd|          t        t        d             y	)
u?   필수 키워드가 추출된 텍스트에 포함되어 있다.r   =u   [키워드 포함 여부]Ou
   X (누락)  z<20 N)r'   printr   r   )r)   r#   r*   kwdl_foundmarks         r   test_keyword_presencez0TestTextExtractionAccuracy.test_keyword_presencee   s|    !.166jo)*jl# 	(BW}H"3DBr#hav&'	(
 	jor   c                     |d   j                   }d}t                t        t        d             t        d       t        t                      t        d       t        |d|        t        t        d             y)uM   첫 500자 샘플을 출력하여 추출 품질을 육안으로 확인한다.r   i  r-   u   [텍스트 샘플 (첫 500자)]z-- opendataloader-pdf --N)r'   r1   r   )r)   r#   r*   
sample_lens       r   test_text_samplez+TestTextExtractionAccuracy.test_text_sampleu   s_    !.166
jo/0jl()gkz"#jor   c                    |d   j                   }t        |      }t                t        t        d             t        d       t        t                      t        d|dd       t        t        d             |dkD  sJ y)	u+   추출된 텍스트 길이를 보고한다.r   r-   u   [텍스트 길이]u'     opendataloader-pdf 텍스트 길이: ,u    문자r   N)r'   r(   r1   r   )r)   r#   r*   dl_lens       r   test_text_length_reportz2TestTextExtractionAccuracy.test_text_length_report   sk    !.166Wjo"#jl7qzIJjozzr   )__name__
__module____qualname____doc__dictstrr   r+   r5   r8   r<   r   r   r   r%   r%   ]   st    /Nd38n N N
S#X 4  4S> d $sCx. T r   r%   c                   *    e Zd ZdZdeeef   ddfdZy)TestTableStructurePreservationu*   항목 2: 표(table) 구조 보존 여부.r#   r   Nc                    |d   j                   }t                t        t        d             t        d       t        t                      t        dt        |              |rt	        |      D ]r  \  }}|j                  dg       }|j                  dg       }t        d| dt        |       d	t        |       d
       t        d|        |sbt        d|d           t nt        d       t        t        d             y)u6   추출한 테이블의 행/열 구조를 출력한다.r   r-   u   [테이블 구조 상세]u     감지된 테이블 수: headersrowsz  Table[z]: u   행 x u   열u       헤더: u       첫 행: r   u     (감지된 테이블 없음)N)tablesr1   r   r(   	enumerateget)r)   r#   	dl_tablesidxtblrF   rG   s          r   test_table_structure_detailz:TestTableStructurePreservation.test_table_structure_detail   s    *4^*D*K*K	jo)*jl+C	N+;<=%i0 5S%(WWY%;(+(;ST6#g,sKLWI./M$q'345 23jor   )r=   r>   r?   r@   rA   rB   r   rN   r   r   r   rD   rD      s     4d38n  r   rD   c                   D    e Zd ZdZdeeef   ddfdZdeeef   ddfdZy)TestArticleNumberAccuracyu3   항목 3: 조항 번호 정확성 (제N조 패턴).r#   r   Nc                    |d   j                   }t        j                  |      }t                t        t	        d             t        d       t        t	                      t        dt        |              t        t        |      d       }t        dt        |              t        d|d	d
  t        |      d
kD  rdnd        t        t	        d             t        |      dkD  sJ d       y	)uT   감지된 조항(제N조) 수를 출력하고 최소 1개 이상인지 확인한다.r   r-   u   [조항 번호(제N조) 감지]u(     opendataloader-pdf 감지 조항 수: c                 \    t        t        j                  d|       j                               S )Nz\d+)intresearchgroup)xs    r   <lambda>z>TestArticleNumberAccuracy.test_article_count.<locals>.<lambda>   s    #bii288:; r   )keyu     unique 조항 수: u     조항 목록: N   z... r   u>   opendataloader: 조항 번호가 하나도 감지되지 않음)r'   ARTICLE_PATTERNfindallr1   r   r(   sortedset)r)   r#   r*   dl_articles	dl_uniques        r   test_article_countz,TestArticleNumberAccuracy.test_article_count   s    !.166%--g6jo/0jl8[9I8JKL;
	 	%c)n%567	#2/Y"9LRT/UV	
 	jo;!#e%ee#r   c                    |d   j                   }t        j                  |      }t                t        t	        d             t        d       t        t	                      t        dt        |              t        t	        d             y)u7   항 번호(① ② ③ 등) 감지 수를 출력한다.r   r-   u   [항 번호(①②③) 감지]u,     opendataloader-pdf 감지 항 번호 수: N)r'   CLAUSE_PATTERNr]   r1   r   r(   )r)   r#   r*   
dl_clausess       r   test_clause_number_countz2TestArticleNumberAccuracy.test_clause_number_count   sg    !.166#++G4
jo./jl<S_<MNOjor   )	r=   r>   r?   r@   rA   rB   r   rb   rf   r   r   r   rP   rP      s>    =fT#s(^ f f04S> d r   rP   c                   D    e Zd ZdZdeeef   ddfdZdeeef   ddfdZy)TestSpecialCharacterHandlingu6   항목 4: 특수문자(「」, ㆍ 등) 처리 여부.r#   r   Nc                    |d   j                   t                t        t        d             t        d       t        t                      t        dddddd	       t        t        d
d             t        D ]2  }j	                  |      }|dkD  r| dnd}t        d|dd|d	       4 t        fdt        D              }t        t                      t        d| dt        t                      t        t        d             y)uC   각 특수문자의 존재 여부와 등장 횟수를 출력한다.r   r-   u   [특수문자 처리]r/   u   문자z<8r0   u   opendataloader-pdf 횟수z>24-$   r   u   회u	   미발견c              3   ,   K   | ]  }|v sd   yw   Nr   .0chr*   s     r   	<genexpr>zJTestSpecialCharacterHandling.test_special_char_presence.<locals>.<genexpr>        DrbGmD   	u     커버 특수문자: /N)r'   r1   r   r
   countsumr(   )r)   r#   rq   dl_countdl_mark
dl_coveredr*   s         @r   test_special_char_presencez7TestSpecialCharacterHandling.test_special_char_presence   s    !.166jo%&jl8B-q!<S ABCjb!" 	0B}}R(H*2Q,
#&KGBrBiq./	0
 D]DD
jl'
|1S5G4HIJjor   c           	      4   |d   j                   }|j                  d      }|j                  d      }t                t        t        d             t        d       t        t                      t        d| d| d||k(          t        t        d             y	)
uO   한글 법령 괄호「」가 온전히 쌍으로 존재하는지 확인한다.r   r   r   r-   u&   [법령 괄호「」쌍 일치 여부]u     opendataloader-pdf - 「:u	   회, 」:u   회, 쌍 일치: N)r'   rv   r1   r   )r)   r#   r*   dl_opendl_closes        r    test_unicode_normalization_checkz=TestSpecialCharacterHandling.test_unicode_normalization_check   s    !.166--&=='jo67jl)')H: F"h./1	
 	jor   )	r=   r>   r?   r@   rA   rB   r   r{   r   r   r   r   rh   rh      s;    @T#s(^  *4S> d r   rh   c                   *    e Zd ZdZdeeef   ddfdZy)TestProcessingSpeedu   항목 5: 처리 속도.r#   r   Nc                 b   |d   }|d   j                   j                  dd      }|dkD  r||z  nd}t                t        t        d             t        d       t        t                      t        d	|d
d       t        d| d|dd       t        t        d             |dkD  sJ d       y)u8   파싱 시간을 출력하고 양수인지 확인한다.r   r   
page_countrn   r   g        r-   u   [처리 속도]u$     opendataloader-pdf 처리 시간: z.3fu   초u     총 페이지: u   , 페이지당: z.4fu,   opendataloader-pdf 처리 시간이 0 이하N)metadatarJ   r1   r   )r)   r#   
dl_elapseddl_pagesdl_per_pages        r   test_parsing_speedz&TestProcessingSpeed.test_parsing_speed  s    &y1
">2;;??aP/7!|j8+jo jl4Z4DCHI!(+;K;LCPQjoA~MMM~r   )r=   r>   r?   r@   rA   rB   r   r   r   r   r   r   r     s#    "NT#s(^ N Nr   r   c                   *    e Zd ZdZdeeef   ddfdZy)TestSummaryReportu   종합 요약 출력.r#   r   Nc           
      T   |d   j                   |d   j                  }|d   }t        j                        }t	        fdt
        D              }t	        fdt        D              }t                t        t        dd             t        d       t        t        dd             t        dd	d
ddd       t        t        dd             t        ddd
dt              d       dt        t               d}t        d|d
d|d       t        ddd
dt        |      d       t        ddd
dt        t        |            d       t        ddd
d|d       t        ddd
d|d       t        t        dd             t                t              dkD  sJ y)uD   모든 항목의 핵심 지표를 한 화면에 요약 출력한다.r   r   c              3   ,   K   | ]  }|v sd   ywrm   r   ro   s     r   rr   z9TestSummaryReport.test_overall_summary.<locals>.<genexpr>8  rs   rt   c              3   ,   K   | ]  }|v sd   ywrm   r   )rp   r2   r*   s     r   rr   z9TestSummaryReport.test_overall_summary.<locals>.<genexpr>9  s     C"R7]ACrt   r-   <   u2   [ opendataloader-pdf 파싱 품질 종합 요약 ]r/   u   항목z<30r0   zopendataloader-pdfz>20rj   u   텍스트 길이 (문자)z>20,u   키워드 검출 (u   개 중)u   감지 테이블 수u   감지 조항 수(제N조)u   특수문자 커버 수u   처리 시간 (초)z>20.3fr   N)r'   rH   r\   r]   rw   r
   r   r1   r   r(   r_   )	r)   r#   rK   r   r`   
dl_specialdl_kw	kw_headerr*   s	           @r   test_overall_summaryz&TestSummaryReport.test_overall_summary1  s   !.166*4^*D*K*K	&y1
%--g6D]DD
C 1CCjb!"BCjb!"8C."6s!;<=jb!".s31S\$4GHI(->)?(@I	9S/5+./)#.aIs/CDE/4Ac#k:J6KC5PQR,S1:c2BCD(-Qz&.ABCjb!"7|ar   )r=   r>   r?   r@   rA   rB   r   r   r   r   r   r   r   .  s      tCH~  $  r   r   )rj   r   )"r@   rT   sysr   typingr   pytestpathinsert
doc_parserr   r   r   r   listrB   __annotations__r
   compiler\   rd   rS   r   fixturebytesr   rA   r#   r%   rD   rP   rh   r   r   r   r   r   <module>r      s=   
 
    - . -K 	  49  LtCy K "**/0 IJS s C  h5    h% DcN   02 2t @& &\' '^N N4   r   