
    iA'                        d Z ddlZddlZddlZddlmZmZ ddlmZ ddlZej                  j                  d e ee      j                  j                  j                               ddlmZmZ  ed      Zdee   defd	Z	 	 	 	 dd
edededededefdZ G d d      Z G d d      Z G d d      Z G d d      Zy)u,   utils/insights_engine.py 테스트 스위트    N)datetime	timedelta)Path)InsightsEngineInsightsSummaryz+/home/jay/workspace/memory/task-timers.jsontasksreturnc                 ^    t        j                  d| D ci c]  }|d   |
 c}i      S c c}w )u+   테스트용 task-timers.json 내용 생성r   task_id)jsondumps)r   ts     Q/home/jay/workspace/.worktrees/task-2116-dev1/utils/tests/test_insights_engine.pymake_task_timersr      s,    ::w% @Q9q @ABB @s   *
r   team_idstatusduration_secondsdays_agoc                     t        j                         t        |      z
  }|t        |      z
  }| ||  d|j                         |j                         ||t	        |dz         ddS )Ndays)secondsu    설명<   u   분)r   r   description
start_timeend_timer   r   duration_human)r   nowr   	isoformatint)r   r   r   r   r   end_dtstart_dts          r   
_make_taskr#      sw     \\^iX66F	*:;;H!'*((*$$&, !12!567s;	 	    c                       e Zd ZdZddZy)TestInsightsSummaryu*   InsightsSummary dataclass 구조 테스트Nc           
         t        ddddddiddd	      }|j                  dk(  sJ |j                  dk(  sJ |j                  dk(  sJ |j                  dk(  sJ |j
                  ddik(  sJ |j                  dddk(  sJ y
)u   필수 필드 존재 확인
      g      @g?	dev1-team      )	completedrunning)total_taskscompleted_tasksavg_duration_minutestotal_estimated_costtasks_by_teamtasks_by_statusN)r   r/   r0   r1   r2   r3   r4   )selfss     r   test_fields_existz%TestInsightsSummary.test_fields_exist0   s    !$!%&**+:
 }}"""  A%%%%%,,,%%---;"2222  !$BBBBr$   r	   N)__name__
__module____qualname____doc__r7    r$   r   r&   r&   -   s    4Cr$   r&   c                   8    e Zd ZdZdeddfdZdeddfdZddZy)	TestInsightsEngineInitu"   InsightsEngine 초기화 테스트tmp_pathr	   Nc                 x    t        t        d      g      }|dz  }|j                  |       t        |      }|J y)u   유효한 경로로 초기화t1task-timers.jsonN)r   r#   
write_textr   r5   r@   datapengines        r   test_init_with_valid_pathz0TestInsightsEngineInit.test_init_with_valid_pathE   sA    D!1 23))	T"!!!r$   c                     t        t        d      g      }|dz  }|j                  |       t        t	        |            }|J y)u   문자열 경로로 초기화rB   rC   N)r   r#   rD   r   strrE   s        r   test_init_with_string_pathz1TestInsightsEngineInit.test_init_with_string_pathM   sE    D!1 23))	TA'!!!r$   c                 "    t        d      }|J y)uI   존재하지 않는 경로도 초기화는 성공 (로드 시 빈 결과)/nonexistent/task-timers.jsonN)r   )r5   rH   s     r   test_init_nonexistent_path_okz4TestInsightsEngineInit.test_init_nonexistent_path_okU   s     ?@!!!r$   r8   )r9   r:   r;   r<   r   rI   rL   rO   r=   r$   r   r?   r?   B   s0    ,"$ "4 ""4 "D ""r$   r?   c                       e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	deddfd
Z
deddfdZdeddfdZddZdeddfdZddZy)TestGetSummaryu   get_summary() 테스트r@   r	   Nc                     t        d      t        d      g}|dz  }|j                  t        |             t        |      }|j	                  d      }t        |t              sJ y)u   InsightsSummary 반환rB   t2rC      r   N)r#   rD   r   r   get_summary
isinstancer   r5   r@   r   rG   rH   results         r   test_returns_insights_summaryz,TestGetSummary.test_returns_insights_summary^   s`    D!:d#34))	%e,-"###,&/222r$   c                     t        d      D cg c]  }t        d| d       }}|dz  }|j                  t        |             t	        |      }|j                  d      }|j                  dk(  sJ yc c}w )	u.   total_tasks는 기간 내 전체 태스크 수r+   r      r   rC   rT   r   N)ranger#   rD   r   r   rU   r/   r5   r@   ir   rG   rH   rX   s          r   test_total_tasks_counts_allz*TestGetSummary.test_total_tasks_counts_allg   sz    :?(CQasGa0CC))	%e,-"###,!!Q&&& Ds   A5c                     t        dd      t        dd      t        dd      g}|dz  }|j                  t        |             t        |      }|j	                  d	      }|j
                  d
k(  sJ y)u0   completed_tasks는 status=completed만 카운트rB   r-   r   rS   t3r.   rC   rT   r   r,   N)r#   rD   r   r   rU   r0   rW   s         r   #test_completed_tasks_filters_statusz2TestGetSummary.test_completed_tasks_filters_statusp   sy     tK0tK0tI.

 ))	%e,-"###,%%***r$   c                     t        dd      t        dd      g}|dz  }|j                  t        |             t        |      }|j	                  d      }t        |j                  d	z
        d
k  sJ y)u'   평균 소요시간 계산 (분 단위)rB   g      ^@)r   rS   g     f@rC   rT   r   g      @g?N)r#   rD   r   r   rU   absr1   rW   s         r   %test_avg_duration_minutes_calculationz4TestGetSummary.test_avg_duration_minutes_calculation}   sy     te4te4
 ))	%e,-"###,6..45;;;r$   c                 H   t        dd      t        dd      t        dd      g}|dz  }|j                  t        |             t        |      }|j	                  d	      }|j
                  j                  d      d
k(  sJ |j
                  j                  d      dk(  sJ y)u   팀별 태스크 집계rB   r*   )r   rS   rc   	dev2-teamrC   rT   r   r,   r[   N)r#   rD   r   r   rU   r3   getrW   s         r   test_tasks_by_team_groupedz)TestGetSummary.test_tasks_by_team_grouped   s     t[1t[1t[1

 ))	%e,-"###,##''4999##''4999r$   c                 H   t        dd      t        dd      t        dd      g}|dz  }|j                  t        |             t        |      }|j	                  d	      }|j
                  j                  d      d
k(  sJ |j
                  j                  d      dk(  sJ y)u   상태별 태스크 집계rB   r-   rb   rS   rc   r.   rC   rT   r   r,   r[   N)r#   rD   r   r   rU   r4   rj   rW   s         r   test_tasks_by_status_groupedz+TestGetSummary.test_tasks_by_status_grouped   s     tK0tK0tI.

 ))	%e,-"###,%%))+6!;;;%%)))4999r$   c                     t        dd      t        dd      g}|dz  }|j                  t        |             t        |      }|j	                  d      }|j
                  d	k(  sJ y
)u(   days 필터: 기간 밖 태스크 제외recentr+   r\   oldr   rC   rT   r   r[   N)r#   rD   r   r   rU   r/   rW   s         r   #test_days_filter_excludes_old_tasksz2TestGetSummary.test_days_filter_excludes_old_tasks   so     x!,ur*
 ))	%e,-"###,!!Q&&&r$   c                     |dz  }|j                  t        j                  di i             t        |      }|j	                  d      }|j
                  dk(  sJ |j                  dk(  sJ y)u    데이터 없으면 0값 SummaryrC   r   rT   r   r   N)rD   r   r   r   rU   r/   r0   r5   r@   rG   rH   rX   s        r   $test_empty_data_returns_zero_summaryz3TestGetSummary.test_empty_data_returns_zero_summary   sk    ))	TZZ"./"###,!!Q&&&%%***r$   c                 `    t        d      }|j                  d      }|j                  dk(  sJ y)u   파일 없으면 0값 SummaryrN   rT   r   r   N)r   rU   r/   r5   rH   rX   s      r   *test_nonexistent_file_returns_zero_summaryz9TestGetSummary.test_nonexistent_file_returns_zero_summary   s4     ?@###,!!Q&&&r$   c                     t        d      D cg c]  }t        d|        }}|dz  }|j                  t        |             t	        |      }|j                  d      }|j                  dk\  sJ yc c}w )u$   비용 추정값은 음수가 아님   r   rC   rT   r   g        N)r]   r#   rD   r   r   rU   r2   r^   s          r   %test_total_estimated_cost_nonnegativez4TestGetSummary.test_total_estimated_cost_nonnegative   sw    .3Ah7asG$77))	%e,-"###,**c111 8s   A3c                     t         j                         st        j                  d       t	        t               }|j                  d      }|j                  dkD  sJ t        |j                  t              sJ y)u   실제 task-timers.json 로드u   task-timers.json 없음im  r   r   N)
TASK_TIMERS_PATHexistspytestskipr   rU   r/   rV   r3   dictrv   s      r   test_real_task_timersz$TestGetSummary.test_real_task_timers   sc    &&(KK12 01###-!!A%%%&..555r$   r8   )r9   r:   r;   r<   r   rY   r`   rd   rg   rk   rm   rq   rt   rw   rz   r   r=   r$   r   rQ   rQ   [   s    !3d 3t 3'D 'T '+D +T +<d <t <:4 :D ::T :d :
'D 
'T 
'+T +d +'2d 2t 26r$   rQ   c                   p    e Zd ZdZdeddfdZdeddfdZdeddfdZdeddfdZdeddfd	Z	deddfd
Z
y)TestRenderAsciiChartu   render_ascii_chart() 테스트r@   r	   Nc                     |dz  }|j                  t        j                  di i             t        |      }|j	                  ddd      }t        |t              sJ y)u
   str 반환t.jsonr   ry   r[   )abNrD   r   r   r   render_ascii_chartrV   rK   rs   s        r   test_returns_stringz(TestRenderAsciiChart.test_returns_string   sT    x	TZZ"./"**+;<&#&&&r$   c                     |dz  }|j                  t        j                  di i             t        |      }|j	                  ddd      }d|v sJ d|v sJ y)	u    레이블이 차트에 포함됨r   r   r(   r+   )r*   ri   r*   ri   NrD   r   r   r   r   rs   s        r   test_contains_keysz'TestRenderAsciiChart.test_contains_keys   s`    x	TZZ"./"**!+LMf$$$f$$$r$   c                     |dz  }|j                  t        j                  di i             t        |      }|j	                  ddi      }d|v sJ y)u   막대 문자(█) 포함r   r   r   r(   u   █Nr   rs   s        r   test_contains_bar_charsz,TestRenderAsciiChart.test_contains_bar_chars   sO    x	TZZ"./"**C95r$   c                     |dz  }|j                  t        j                  di i             t        |      }|j	                  ddid      }d|v sJ y)u   title 인자 반영r   r   xr[   u   팀별 태스크)titleNr   rs   s        r   test_with_titlez$TestRenderAsciiChart.test_with_title   sW    x	TZZ"./"**C8;M*N!V+++r$   c                     |dz  }|j                  t        j                  di i             t        |      }|j	                  i       }t        |t              sJ y)uD   빈 데이터는 에러 없이 빈 문자열 또는 메시지 반환r   r   Nr   rs   s        r   test_empty_dataz$TestRenderAsciiChart.test_empty_data   sO    x	TZZ"./"**2.&#&&&r$   c                    |dz  }|j                  t        j                  di i             t        |      }|j	                  ddd      }|j                         D cg c]  }d|v sd|v s| }}t        |      dk(  sJ t        d	 |D              }t        d
 |D              }t        |      t        |      kD  sJ yc c}w )u   큰 값이 더 긴 막대r   r   d   r[   )bigsmallr   r   r,   c              3   *   K   | ]  }d |v s|  yw)r   Nr=   .0ls     r   	<genexpr>zHTestRenderAsciiChart.test_larger_value_has_longer_bar.<locals>.<genexpr>  s     7aEQJ7   	c              3   *   K   | ]  }d |v s|  yw)r   Nr=   r   s     r   r   zHTestRenderAsciiChart.test_larger_value_has_longer_bar.<locals>.<genexpr>	  s     ;gl!;r   N)rD   r   r   r   r   
splitlineslennext)	r5   r@   rG   rH   rX   r   linesbig_line
small_lines	            r    test_larger_value_has_longer_barz5TestRenderAsciiChart.test_larger_value_has_longer_bar   s    x	TZZ"./"**3+CD"--/Nq5A:ANN5zQ7577;U;;
8}s:...	 Os   B?+B?)r9   r:   r;   r<   r   r   r   r   r   r   r   r=   r$   r   r   r      sw    ('D 'T '%4 %D %  , , ,' ' '
/ 
/$ 
/r$   r   )r*   r-   g     r@r[   )r<   r   systempfiler   r   pathlibr   r~   pathinsertrK   __file__parentutils.insights_enginer   r   r|   listr   r   floatr    r#   r&   r?   rQ   r   r=   r$   r   <module>r      s    2  
  (   3tH~,,33::; < AEF CDJ C3 C #  	
  
*C C*" "2v6 v6r6/ 6/r$   