
    i /                        d Z ddlZddlmc mZ ddlZddlZddl	Z	ddl
Z
ddlZe	j                  j                  de
j                  j                  e
j                  j                  e      d             ddlmZmZmZmZmZmZ g dZg dZdZ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   conversion_tracker.py 단위 테스트.

TDD RED→GREEN 방식으로 작성된 테스트.
모든 테스트 데이터는 명시적으로 "샘플 데이터"로 표기됨.
    Nz..)calculate_funnelcalculate_dropoffanalyze_ai_sourcesgenerate_insights	parse_csvbuild_report))   AI 검색 도착  )   콘텐츠 소비^  )   인터랙션x   )   관심<   )   전환   )	   재방문
   )   추천   ))r	      ChatGPT)r	   r   
Perplexity)r	      Gemini)r      r   )r      r   )r      r   uq   stage,users
AI 검색 도착,500
콘텐츠 소비,350
인터랙션,120
관심,60
전환,25
재방문,10
추천,3
u   stage,users,source
AI 검색 도착,180,ChatGPT
AI 검색 도착,120,Perplexity
AI 검색 도착,200,Gemini
전환,12,ChatGPT
전환,8,Perplexity
전환,5,Gemini
c                   $    e Zd Zd Zd Zd Zd Zy)TestParseCsvc                 "   t        t        j                  t                    }t	        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }t        t        j                  |            d	x}x}}|d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }t        t        j                  |            d	x}x}}|d
   }|j                  }d} ||      }
d	}|
|u }|st        j                  d|fd|
|f      t        j                  |      t        j                  |      t        j                  |      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}x}x}
x}}y	)u5   소스 컬럼 없는 CSV 파싱 — 샘플 데이터.   ==z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenrowspy0py1py3py6assert %(py8)spy8Nr   stager	   z%(py1)s == %(py4)sr*   py4assert %(py6)sr,   usersr
   source)is)zJ%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.get
}(%(py5)s)
} is %(py10)s)r*   r+   py5py7py10assert %(py12)spy12)r   ioStringIOSAMPLE_CSV_NO_SOURCEr&   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationget)selfr'   @py_assert2@py_assert5@py_assert4@py_format7@py_format9@py_assert0@py_assert3@py_format5@py_assert6@py_assert9@py_assert8@py_format11@py_format13s                  H/home/jay/workspace/tools/geo-analytics/tests/test_conversion_tracker.pytest_parse_csv_no_source_columnz,TestParseCsv.test_parse_csv_no_source_columnM   s   %9:;4yAyA~yAss44yAAww5#55#55555#5555555#55555555Aww&3&3&&&&3&&&&&&3&&&&&&&Aw,w{{,8,{8$,,$,,,,$,,,w,,,{,,,8,,,$,,,,,,,,,,,    c                 t   t        t        j                  t                    }t	        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }t        t        j                  |            d	x}x}}|d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }	dd|	iz  }t        t        j                  |            d	x}x}}y	)u5   소스 컬럼 있는 CSV 파싱 — 샘플 데이터.   r#   r%   r&   r'   r(   r-   r.   Nr   r5   r   r0   r1   r3   r,   r4   r   )r   r<   r=   SAMPLE_CSV_WITH_SOURCEr&   r?   r@   rA   rB   rC   rD   rE   rF   )
rH   r'   rI   rJ   rK   rL   rM   rN   rO   rP   s
             rV   !test_parse_csv_with_source_columnz.TestParseCsv.test_parse_csv_with_source_columnU   sM   %;<=4yAyA~yAss44yAAwx -I- I---- I--- ---I-------Aww&3&3&&&&3&&&&&&3&&&&&&&rX   c                 H   t        t        j                  t                    }|D ]  }|d   }t	        |t
              }|sddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  |      dz  }t        t        j                  |            dx}} y)uC   users 값이 정수로 파싱되는지 확인 — 샘플 데이터.r4   z5assert %(py5)s
{%(py5)s = %(py0)s(%(py2)s, %(py3)s)
}
isinstanceint)r)   py2r+   r7   N)r   r<   r=   r>   r^   r_   rA   rB   r?   rC   rD   rE   rF   )rH   r'   row@py_assert1rK   @py_format6s         rV   !test_parse_csv_users_are_integersz.TestParseCsv.test_parse_csv_users_are_integers\   s    %9:; 	1C!'l0:lC00000000:000:000l000000C000C0000000000	1rX   c                    t        t        j                  d            }g }||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)	u    빈 CSV 파일 엣지 케이스.zstage,users
r#   z%(py0)s == %(py3)sr'   r)   r+   assert %(py5)sr7   N)r   r<   r=   r?   r@   rA   rB   rC   rD   rE   rF   )rH   r'   rI   rb   @py_format4rc   s         rV   test_parse_csv_empty_filez&TestParseCsv.test_parse_csv_empty_fileb   sm    _56trztrttrrX   N)__name__
__module____qualname__rW   r\   rd   rj    rX   rV   r    r    L   s    -'1rX   r    c                   6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestCalculateFunnelc                 &   t        t              }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}d
}|d   }||v}|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)u4   첫 번째 단계는 rate=100% — 샘플 데이터.r   ratez100%r#   r0   r1   r3   r,   Ndropoff)not in)z%(py1)s not in %(py4)sr   SAMPLE_STAGE_DATAr?   r@   rD   rE   rF   rH   funnelrN   rO   rI   rP   rL   s          rV    test_funnel_first_stage_rate_100z4TestCalculateFunnel.test_funnel_first_stage_rate_100n   s    !"34ay *F* F**** F*** ***F*******)q	)y	))))y	)))y)))	)))))))rX   c                 B   t        t              }t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
u$   7단계 퍼널 — 샘플 데이터.r"   r#   r%   r&   rx   r(   r-   r.   N)r   rv   r&   r?   r@   rA   rB   rC   rD   rE   rF   )rH   rx   rI   rJ   rK   rL   rM   s          rV   test_funnel_stages_countz,TestCalculateFunnel.test_funnel_stages_countt   s    !"346{a{a{ass66{arX   c                 .   t        t              }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)u&   users 값 보존 — 샘플 데이터.r   r4   r
   r#   r0   r1   r3   r,   N   r   ru   rw   s          rV   test_funnel_users_preservedz/TestCalculateFunnel.test_funnel_users_preservedy   s    !"34ay!(S(!S((((!S(((!(((S(((((((ay!'R'!R''''!R'''!'''R'''''''rX   c                 .   t        t              }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}|d
   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)u)   stage 이름 보존 — 샘플 데이터.r   r/   r	   r#   r0   r1   r3   r,   Nr}   r   ru   rw   s          rV   test_funnel_stage_namesz+TestCalculateFunnel.test_funnel_stage_names   s    !"34ay!7%77!%77777!%7777!777%77777777ay!-X-!X----!X---!---X-------rX   c                 (   t        t              }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
u@   두 번째 단계 rate = 350/500*100 = 70% — 샘플 데이터.   rr   z70.0%r#   r0   r1   r3   r,   Nru   rw   s          rV   test_funnel_second_stage_ratez1TestCalculateFunnel.test_funnel_second_stage_rate   sc    !"34ay +G+ G++++ G+++ +++G+++++++rX   c                    t        t              }|dd D ]  }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd	|iz  }t        t        j                  |            dx}} y)
uG   첫 번째 제외 모든 단계에 dropoff 존재 — 샘플 데이터.r   Nrs   inz%(py1)s in %(py3)sr/   r*   r+   rh   r7   )
r   rv   r?   r@   rD   rA   rB   rC   rE   rF   )rH   rx   r/   rN   rI   ri   rc   s          rV   )test_funnel_all_have_dropoff_except_firstz=TestCalculateFunnel.test_funnel_all_have_dropoff_except_first   s{    !"34ABZ 	&E%9%%%%9%%%9%%%%%%%%%%%%%%%%	&rX   c                 f   t        g       }g }||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)u   빈 데이터 엣지 케이스.r#   rf   rx   rg   rh   r7   N)	r   r?   r@   rA   rB   rC   rD   rE   rF   )rH   rx   rI   rb   ri   rc   s         rV   test_funnel_empty_dataz*TestCalculateFunnel.test_funnel_empty_data   sd    !"%v|vvvrX   N)
rk   rl   rm   ry   r{   r~   r   r   r   r   rn   rX   rV   rp   rp   m   s%    * 
(.,
&rX   rp   c                   *    e Zd Zd Zd Zd Zd Zd Zy)TestCalculateDropoffc                    t        dd      }t        j                  }d} ||      }||k(  }|s
t        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)uE   기본 드롭오프율: (500-350)/500*100 = 30% — 샘플 데이터.r
   r   g      >@r#   zL%(py0)s == %(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s.approx
}(%(py6)s)
}resultpytestr)   r`   r2   r,   r.   assert %(py10)sr9   Nr   r   approxr?   r@   rA   rB   rC   rD   rE   rF   rH   r   rO   rJ   @py_assert7rb   rM   rT   s           rV   test_dropoff_basicz'TestCalculateDropoff.test_dropoff_basic   s    "3,,t,t,,v,,,,,v,,,,,,,v,,,v,,,,,,,,,,,,,,,t,,,,,,,,,,,rX   c                 h   t        dd      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}}y
)uD   이전 단계 users=0 엣지 케이스 — ZeroDivisionError 방지.r   d           r#   rf   r   rg   rh   r7   N)	r   r?   r@   rA   rB   rC   rD   rE   rF   rH   r   rI   rb   ri   rc   s         rV   test_dropoff_zero_previousz/TestCalculateDropoff.test_dropoff_zero_previous   sf    "1c*v}vvvrX   c                    t        dd      }t        j                  }d} ||      }||k(  }|s
t        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }dd	|iz  }t        t        j                  |            d
x}x}x}}y
)uD   드롭오프 없는 경우 (이전=현재): 0% — 샘플 데이터.r   r   r#   r   r   r   r   r   r9   Nr   r   s           rV   test_dropoff_no_dropoffz,TestCalculateDropoff.test_dropoff_no_dropoff   s    "3,+s+s++v+++++v+++++++v+++v+++++++++++++++s+++++++++++rX   c                    t        dd      }t        j                  }d} ||      }||k(  }|s
t        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)u)   전체 이탈: 100% — 샘플 데이터.r   r   g      Y@r#   r   r   r   r   r   r9   Nr   r   s           rV   test_dropoff_full_dropoffz.TestCalculateDropoff.test_dropoff_full_dropoff   s    "3*-u-u--v-----v-------v---v---------------u-----------rX   c                    t        dd      }t        j                  }d} ||      }||k(  }|s
t        j                  d|fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }d	d
|iz  }t        t        j                  |            dx}x}x}}y)uP   인터랙션→관심 드롭오프: (120-60)/120*100 = 50% — 샘플 데이터.r   r   g      I@r#   r   r   r   r   r   r9   Nr   r   s           rV   &test_dropoff_interaction_to_conversionz;TestCalculateDropoff.test_dropoff_interaction_to_conversion   s    "3+,t,t,,v,,,,,v,,,,,,,v,,,v,,,,,,,,,,,,,,,t,,,,,,,,,,,rX   N)rk   rl   rm   r   r   r   r   r   rn   rX   rV   r   r      s    -

,
.
-rX   r   c                   0    e Zd Zd Zd Zd Zd Zd Zd Zy)TestAnalyzeAiSourcesc                     t        t              }d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d	}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}d
}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y)uS   샘플 소스 데이터에 ChatGPT, Perplexity, Gemini 포함 — 샘플 데이터.r   r   r   r   r   rh   r7   Nr   r   )
r   SAMPLE_SOURCE_DATAr?   r@   rD   rA   rB   rC   rE   rF   )rH   r   rN   rI   ri   rc   s         rV   test_sources_presentz)TestAnalyzeAiSources.test_sources_present   s   #$67"yF""""yF"""y""""""F"""F"""""""%|v%%%%|v%%%|%%%%%%v%%%v%%%%%%%!x6!!!!x6!!!x!!!!!!6!!!6!!!!!!!rX   c                 (   t        t              }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
u*   ChatGPT arrivals=180 — 샘플 데이터.r   arrivalsr   r#   r0   r1   r3   r,   Nr   r   r?   r@   rD   rE   rF   rH   r   rN   rO   rI   rP   rL   s          rV   test_arrivals_correctz*TestAnalyzeAiSources.test_arrivals_correct   sd    #$67i ,33,3333,333,3333333333rX   c                 (   t        t              }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d	x}x}}y	)
u,   ChatGPT conversions=12 — 샘플 데이터.r   conversionsr   r#   r0   r1   r3   r,   Nr   r   s          rV   test_conversions_correctz-TestAnalyzeAiSources.test_conversions_correct   sd    #$67i /525/25555/2555/55525555555rX   c           	          t        t              }t        |d   d   j                  dd            }t        j
                  }d}d} |||      }||k(  }|st        j                  d|fd	||f      d
t        j                         v st        j                  |      rt        j                  |      nd
dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}x}x}}y)u6   ChatGPT CVR = 12/180*100 = 6.67% — 샘플 데이터.r   cvr% gGz@g{Gz?)relr#   )z[%(py0)s == %(py10)s
{%(py10)s = %(py4)s
{%(py4)s = %(py2)s.approx
}(%(py6)s, rel=%(py8)s)
}cvr_valr   )r)   r`   r2   r,   r.   r9   r:   r;   N)r   r   floatreplacer   r   r?   r@   rA   rB   rC   rD   rE   rF   )
rH   r   r   rO   rJ   r   rR   rb   rT   rU   s
             rV   test_cvr_calculationz)TestAnalyzeAiSources.test_cvr_calculation   s    #$67y)%088bAB --77$7-$77w77777w7777777w777w777777&777&777-777777$777777777777rX   c                 f   t        g       }i }||k(  }|st        j                  d|fd||f      dt        j                         v st        j
                  |      rt        j                  |      ndt        j                  |      dz  }dd|iz  }t        t        j                  |            dx}}y)u&   빈 소스 데이터 엣지 케이스.r#   rf   r   rg   rh   r7   N)	r   r?   r@   rA   rB   rC   rD   rE   rF   r   s         rV   test_empty_source_dataz+TestAnalyzeAiSources.test_empty_source_data   sd    #B'v|vvvrX   c                 ,   dg}t        |      }|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }t	        t        j
                  |            d
x}x}}|d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd	|iz  }t	        t        j
                  |            d
x}x}}y
)uB   전환 단계 없는 소스는 conversions=0 — 샘플 데이터.)r	   r   Clauder   r   r   r#   r0   r1   r3   r,   Nr   z0.0%)r   r?   r@   rD   rE   rF   )rH   datar   rN   rO   rI   rP   rL   s           rV   $test_source_without_conversion_stagez9TestAnalyzeAiSources.test_source_without_conversion_stage   s    34#D)h.3!3.!3333.!333.333!3333333h&0&0&&0000&&000&000&0000000rX   N)	rk   rl   rm   r   r   r   r   r   r   rn   rX   rV   r   r      s     "4
6
8
1rX   r   c                   6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestGenerateInsightsc                 T    t        t              | _        t        t              | _        y)u4   샘플 데이터로 퍼널 및 소스 분석 준비.N)r   rv   rx   r   r   sources)rH   s    rV   setup_methodz!TestGenerateInsights.setup_method   s    &'89)*<=rX   c                    t        | j                  | j                        }t        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)u6   인사이트 결과가 리스트 — 샘플 데이터.5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}r^   insightslistr)   r*   r`   r2   N)r   rx   r   r^   r   rA   rB   r?   rC   rD   rE   rF   rH   r   rO   rP   s       rV   test_insights_is_listz*TestGenerateInsights.test_insights_is_list   s    $T[[$,,?(D))))))))z)))z))))))()))())))))D)))D))))))))))rX   c                    t        | j                  | j                        }d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u>   최대 이탈 지점 인사이트 포함 — 샘플 데이터.c              3   $   K   | ]  }d |v  
 yw)u   최대 이탈Nrn   .0is     rV   	<genexpr>zETestGenerateInsights.test_insights_has_max_dropoff.<locals>.<genexpr>   s     :A?a':   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr)   r`   r2   Nr   rx   r   r   rA   rB   r?   rC   rD   rE   rF   rH   r   rb   rO   rP   s        rV   test_insights_has_max_dropoffz2TestGenerateInsights.test_insights_has_max_dropoff   su    $T[[$,,?:::s:::::::::s:::s::::::::::::::rX   c                    t        | j                  | j                        }d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u>   최고 전환 소스 인사이트 포함 — 샘플 데이터.c              3   $   K   | ]  }d |v  
 yw)u   최고 전환 소스Nrn   r   s     rV   r   zETestGenerateInsights.test_insights_has_best_source.<locals>.<genexpr>        A1)Q.Ar   r   r   r   Nr   r   s        rV   test_insights_has_best_sourcez2TestGenerateInsights.test_insights_has_best_source   u    $T[[$,,?AAAsAAAAAAAAAsAAAsAAAAAAAAAAAAAArX   c                    t        | j                  | j                        }d |D        }t        |      }|sddt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}y)u>   최저 전환 소스 인사이트 포함 — 샘플 데이터.c              3   $   K   | ]  }d |v  
 yw)u   최저 전환 소스Nrn   r   s     rV   r   zFTestGenerateInsights.test_insights_has_worst_source.<locals>.<genexpr>   r   r   r   r   r   Nr   r   s        rV   test_insights_has_worst_sourcez3TestGenerateInsights.test_insights_has_worst_source   r   rX   c                 \   t        g i       }t        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}y)u8   빈 퍼널 엣지 케이스 — 크래시 없어야 함.r   r^   r   r   r   N)
r   r^   r   rA   rB   r?   rC   rD   rE   rF   r   s       rV   test_insights_empty_funnelz/TestGenerateInsights.test_insights_empty_funnel   s    $R,(D))))))))z)))z))))))()))())))))D)))D))))))))))rX   c                 d   t        | j                  | j                        }t        |      }d}||k\  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              nddt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}}y	)
u5   인사이트 최소 1개 이상 — 샘플 데이터.r   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)sr&   r   r(   r-   r.   N)r   rx   r   r&   r?   r@   rA   rB   rC   rD   rE   rF   )rH   r   rI   rJ   rK   rL   rM   s          rV   test_insights_min_countz,TestGenerateInsights.test_insights_min_count  s    $T[[$,,?8}!!}!!!!}!!!!!!s!!!s!!!!!!8!!!8!!!}!!!!!!!!!!rX   N)
rk   rl   rm   r   r   r   r   r   r   r   rn   rX   rV   r   r      s'    >
*
;
B
B
*
"rX   r   c                   6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestBuildReportc                 v   t        t        t              }d}||v }|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y)	u4   리포트에 funnel 키 존재 — 샘플 데이터.rx   r   r   reportr   rh   r7   Nr   rv   r   r?   r@   rD   rA   rB   rC   rE   rF   rH   r   rN   rI   ri   rc   s         rV   test_report_has_funnel_keyz*TestBuildReport.test_report_has_funnel_key  si    /1CD!x6!!!!x6!!!x!!!!!!6!!!6!!!!!!!rX   c                 v   t        t        t              }d}||v }|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y)	uA   리포트에 ai_source_breakdown 키 존재 — 샘플 데이터.ai_source_breakdownr   r   r   r   rh   r7   Nr   r   s         rV   'test_report_has_ai_source_breakdown_keyz7TestBuildReport.test_report_has_ai_source_breakdown_key  sl    /1CD$.$....$...$................rX   c                 v   t        t        t              }d}||v }|st        j                  d|fd||f      t        j
                  |      dt        j                         v st        j                  |      rt        j
                  |      nddz  }dd|iz  }t        t        j                  |            dx}}y)	u6   리포트에 insights 키 존재 — 샘플 데이터.r   r   r   r   r   rh   r7   Nr   r   s         rV   test_report_has_insights_keyz,TestBuildReport.test_report_has_insights_key  si    /1CD#zV####zV###z######V###V#######rX   c                    t        t        t              }t        j                  |d      }t        j
                  |      }|d   d   d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      d	z  }d
d|iz  }t        t        j                  |            dx}x}}y)u8   리포트가 JSON 직렬화 가능 — 샘플 데이터.F)ensure_asciirx   r   r/   r	   r#   r0   r1   r3   r,   N)r   rv   r   jsondumpsloadsr?   r@   rD   rE   rF   )	rH   r   dumpedloadedrN   rO   rI   rP   rL   s	            rV   test_report_json_serializablez-TestBuildReport.test_report_json_serializable  s    /1CDF7F#h"7+A/AA+/AAAAA+/AAAA+AAA/AAAAAAAArX   c                     t        t        t              }|d   }t        |      }d}||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            d	x}x}x}}y	)
u$   퍼널 7단계 — 샘플 데이터.rx   r"   r#   )z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr&   )r)   r`   r2   r8   zassert %(py9)spy9N)r   rv   r   r&   r?   r@   rA   rB   rC   rD   rE   rF   )rH   r   rb   rO   rQ   rJ   @py_format8@py_format10s           rV   test_report_funnel_lengthz)TestBuildReport.test_report_funnel_length&  s    /1CD(#)s#$))$))))$))))))s)))s)))#)))$))))))))))rX   c                 $   t        t        g       }|d   }i }||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}}y)uB   소스 데이터 없을 때 리포트 생성 — 샘플 데이터.r   r#   r0   r1   r3   r,   N)r   rv   r?   r@   rD   rE   rF   )rH   r   rN   rO   rI   rP   rL   s          rV   test_report_no_source_dataz*TestBuildReport.test_report_no_source_data+  sb    /4+,22,2222,222,2222222222rX   c                    g d}t        |g       }|d   }t        d |D              }|d   }|j                  }d}d} |||      }	t        |	      }
t        j
                  }d} ||      }|
|k(  }|st        j                  d|fd	|
|f      d
t        j                         v st        j                  t              rt        j                  t              nd
t        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |	      t        j                  |
      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}x}	x}
x}x}x}}t        d |D              }|d   }|j                  }d}d} |||      }	t        |	      }
t        j
                  }d} ||      }|
|k(  }|st        j                  d|fd	|
|f      d
t        j                         v st        j                  t              rt        j                  t              nd
t        j                  |      t        j                  |      t        j                  |      t        j                  |      t        j                  |	      t        j                  |
      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}x}	x}
x}x}x}}y)u;   보험 도메인 샘플 데이터 — 실제 비율 검증.))r	   i  )r   i  )r   r   )r   P   )r      )r      )r   r}   rx   c              3   2   K   | ]  }|d    dk(  s|  yw)r/   r   Nrn   r   fs     rV   r   zFTestBuildReport.test_report_insurance_domain_sample.<locals>.<genexpr>?  s     LaQwZ85KL   rr   r   r   g      @r#   )z%(py12)s
{%(py12)s = %(py0)s(%(py10)s
{%(py10)s = %(py4)s
{%(py4)s = %(py2)s.replace
}(%(py6)s, %(py8)s)
})
} == %(py20)s
{%(py20)s = %(py16)s
{%(py16)s = %(py14)s.approx
}(%(py18)s)
}r   r   )r)   r`   r2   r,   r.   r9   r;   py14py16py18py20zassert %(py22)spy22Nc              3   2   K   | ]  }|d    dk(  s|  yw)r/   r   Nrn   r  s     rV   r   zFTestBuildReport.test_report_insurance_domain_sample.<locals>.<genexpr>B  s     S1!G*@R2RQSr  rs   g     A@)r   nextr   r   r   r   r?   r@   rA   rB   rC   rD   rE   rF   )rH   insurance_stagesr   rx   conversion_stagerb   rO   rJ   r   rR   @py_assert11@py_assert15@py_assert17@py_assert19@py_assert13@py_format21@py_format23content_stages                     rV   #test_report_insurance_domain_samplez3TestBuildReport.test_report_insurance_domain_sample0  s   
 .3!L6LL%f-U-55UcU2U5c2>Uu>?U6==UQTU=QTCUU?CUUUUU?CUUUUUUUuUUUuUUU-UUU5UUUcUUU2UUU>UUU?UUUUUU6UUU6UUU=UUUQTUUUCUUUUUUUUUUSSS"9-V-55VcV2V5c2>Vu>?V6==VQUV=QUCVV?CVVVVV?CVVVVVVVuVVVuVVV-VVV5VVVcVVV2VVV>VVV?VVVVVV6VVV6VVV=VVVQUVVVCVVVVVVVVVVrX   N)
rk   rl   rm   r   r   r   r   r   r   r  rn   rX   rV   r   r     s'    "
/
$
B*
3
WrX   r   )"__doc__builtinsrA   _pytest.assertion.rewrite	assertionrewriter?   r<   r   sysosr   pathinsertjoindirname__file__conversion_trackerr   r   r   r   r   r   rv   r   r>   r[   r    rp   r   r   r   r   rn   rX   rV   <module>r(     s     	  
 	  277<< 94@ A 	     B& &\- -@"1 "1T"" ""T4W 4WrX   