
    i&                        U 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	m
Z
mZmZ ddlZej                  j                  d ee      j"                  j"                  dz        Zeej&                  J ej                  j)                  e      Ze
ed<   ej&                  j/                  e        G d	 d
      Z G d d      Z G d d      Z G d d      Z G d d      Zy)u^   
tests for weekly-report.py

[task-794.1] P6-2 주간 메트릭 리포트 스크립트 검증
    Ndatetime	timedelta)Path)AnyDictListweekly_reportzweekly-report.pywrc                   8    e Zd ZdZddZddZddZddZddZy)	TestParseDtu   parse_dt 함수 테스트Nc                     t         j                  d      }|J |j                  dk(  sJ |j                  dk(  sJ |j                  dk(  sJ |j
                  J y)u#   timezone-naive ISO 문자열 파싱z2026-03-22T10:50:37.320125N        )r   parse_dtyearmonthdaytzinfoselfdts     Q/home/jay/workspace/.worktrees/task-2116-dev1/scripts/tests/test_weekly_report.pytest_parses_iso_naivez!TestParseDt.test_parses_iso_naive   s[    [[56~~ww$xx1}}vv||yy       c                 R    t         j                  d      }|J |j                  J y)u   'Z' suffix 제거 후 파싱z2026-03-22T10:50:37ZN)r   r   r   r   s     r   test_strips_z_suffixz TestParseDt.test_strips_z_suffix&   s+    [[/0~~yy   r   c                 2    t         j                  d      J y)u   None 입력 시 None 반환Nr   r   r   s    r   test_returns_none_for_nonez&TestParseDt.test_returns_none_for_none,   s    {{4 (((r   c                 2    t         j                  d      J y)u$   빈 문자열 입력 시 None 반환 Nr    r!   s    r   "test_returns_none_for_empty_stringz.TestParseDt.test_returns_none_for_empty_string0   s    {{2&&&r   c                 2    t         j                  d      J y)u'   잘못된 형식 입력 시 None 반환z
not-a-dateNr    r!   s    r   $test_returns_none_for_invalid_formatz0TestParseDt.test_returns_none_for_invalid_format4   s    {{<(000r   returnN)	__name__
__module____qualname____doc__r   r   r"   r%   r'    r   r   r   r      s    #!!)'1r   r   c                   L    e Zd ZdZddedededeeef   fdZddZ	dd	Z
dd
Zy)TestFilterTasksByPeriodu'   filter_tasks_by_period 함수 테스트task_idstart_offset_daysstatusr)   c                 p    t        j                         t        |      z
  j                         }|d|d |dS )Ndays	dev1-team)r1   team_id
start_timeend_timer3   )r   nowr   	isoformat)r   r1   r2   r3   r9   s        r   
_make_taskz"TestFilterTasksByPeriod._make_task<   s:    llny6G'HHSSU
"$
 	
r   Nc                     | j                  dd      g}t        j                         }t        j	                  ||t        d      z
  |      }t        |      dk(  sJ y)u%   기간 내 시작된 작업은 포함task-1.1r   r2      r5      Nr=   r   r;   r   filter_tasks_by_periodr   lenr   tasksr;   results       r    test_includes_task_within_periodz8TestFilterTasksByPeriod.test_includes_task_within_periodF   sR    qABlln**5#	q8I2I3O6{ar   c                     | j                  dd      g}t        j                         }t        j	                  ||t        d      z
  |      }t        |      dk(  sJ y)u   기간 밖 작업은 제외r?   
   r@   rA   r5   r   NrC   rF   s       r   !test_excludes_task_outside_periodz9TestFilterTasksByPeriod.test_excludes_task_outside_periodM   sR    rBClln**5#	q8I2I3O6{ar   c                     | j                  ddd      g}t        j                         }t        j	                  ||t        d      z
  |      }t        |      dk(  sJ y)u-   기간 내 시작된 running 작업도 포함r?   rB   running)r2   r3   rA   r5   NrC   rF   s       r   /test_running_task_included_if_started_in_periodzGTestFilterTasksByPeriod.test_running_task_included_if_started_in_periodT   sT    qSTlln**5#	q8I2I3O6{ar   )	completedr(   )r*   r+   r,   r-   strintr   r   r=   rI   rL   rO   r.   r   r   r0   r0   9   sB    1
# 
# 
s 
]abegjbj]k 
   r   r0   c                   l    e Zd ZdZdeeeef      fdZddZ	ddZ
ddZddZdd	Zdd
ZddZddZy)TestAggregateu   aggregate 함수 테스트r)   c           	      >    ddddddddddd	dd
ddd d dddddddgS )Nr?   r7   rP        r@PASS)r1   r8   r3   duration_seconds	qc_resultztask-1.2g     @FAILztask-1.3z	dev2-teamrN   ztask-1.4stalez2026-03-21T10:00:00g      @)r1   r8   r3   stale_atrX   r.   r!   s    r   _make_taskszTestAggregate._make_tasks_   sd     &&%$)# &&%$)# &&#$(! &&!1$)-
 	
r   Nc                 ^    t         j                  | j                               }|d   dk(  sJ y)u   총 작업 수 계산total   Nr   	aggregater]   r   rH   s     r   test_total_countzTestAggregate.test_total_count   +    d..01g!###r   c                 ^    t         j                  | j                               }|d   dk(  sJ y)u   완료 작업 수 계산rP      Nra   rc   s     r   test_completed_countz"TestAggregate.test_completed_count   s,    d..01k"a'''r   c                 ^    t         j                  | j                               }|d   dk(  sJ y)u   stale 작업 수 계산r[   rB   Nra   rc   s     r   test_stale_countzTestAggregate.test_stale_count   re   r   c                 ^    t         j                  | j                               }|d   dk(  sJ y)u   running 작업 수 계산rN   rB   Nra   rc   s     r   test_running_countz TestAggregate.test_running_count   s,    d..01i A%%%r   c                     t         j                  | j                               }|d   dk(  sJ |d   dk(  sJ |d   dk(  sJ y)u    QC 집계: PASS 1, FAIL 1, N/A 2qc_passrB   qc_failqc_narg   Nra   rc   s     r   test_qc_countszTestAggregate.test_qc_counts   sQ    d..01i A%%%i A%%%g!###r   c                 ^    t         j                  | j                               }|d   dk(  sJ y)u   QC FAIL 비율: 1/(1+1) = 50%qc_fail_pctg      I@Nra   rc   s     r   test_qc_fail_percentagez%TestAggregate.test_qc_fail_percentage   s,    d..01m$,,,r   c                 d    t         j                  | j                               }|d   d   dk(  sJ y)u'   팀별 평균 소요시간 (분 단위)team_avg_minutesr7   g      @Nra   rc   s     r   test_team_avg_minutesz#TestAggregate.test_team_avg_minutes   s2    d..01()+6#===r   c                 L    dddddg}t         j                  |      }|d   J y)u%   QC 데이터 없을 때 fail_pct=Noner?   r7   rP   g      Y@)r1   r8   r3   rX   rs   N)r   rb   )r   rG   rH   s      r    test_no_qc_data_returns_none_pctz.TestAggregate.test_no_qc_data_returns_none_pct   s3    'K;lqrse$m$,,,r   r(   )r*   r+   r,   r-   r	   r   rQ   r   r]   rd   rh   rj   rl   rq   rt   rw   ry   r.   r   r   rT   rT   \   sG    $
T$sCx.1 
@$
(
$
&
$-
>-r   rT   c                   F    e Zd ZdZdeeef   fdZd	dZd	dZ	d	dZ
d	dZy)
TestBuildReportu   build_report 함수 테스트r)   c                 >    ddddddddddddddd	gddddd
	iddig dS )NrK   	   r   rB      r`   g333330@r7   rV   )	r_   rP   r[   rN   duration_seconds_listrn   ro   qc_warnrp   g      @)r_   rP   r[   rN   rn   ro   r   rp   rs   
team_statsrv   stale_detailsr.   r!   s    r   _make_metricszTestBuildReport._make_metrics   s^    !" .3W   
 "-c 21
 	
r   Nc           	          t        j                         }t        j                  | j	                         g ||t        d      z
  |      }d|v sJ y)u   리포트에 헤더 포함rA   r5   u   # 주간 메트릭 리포트Nr   r;   r   build_reportr   r   r   r;   reports      r   test_contains_headerz$TestBuildReport.test_contains_header   sF    lln!3!3!5r3iUVFW@WY\]-777r   c           	          t        j                         }t        j                  | j	                         g ||t        d      z
  |      }d|v sJ d|v sJ y)u   요약 섹션 포함rA   r5   u   총 작업: 10건u   완료: 9건Nr   r   s      r   test_contains_summaryz%TestBuildReport.test_contains_summary   sT    lln!3!3!5r3iUVFW@WY\]"f,,,'''r   c           	          t        j                         }t        j                  | j	                         g ||t        d      z
  |      }d|v sJ d|v sJ y)u   팀별 통계 표 포함rA   r5   u   ## 팀별 통계r7   Nr   r   s      r   test_contains_team_stats_tablez.TestBuildReport.test_contains_team_stats_table   sT    lln!3!3!5r3iUVFW@WY\]!V+++f$$$r   c           	          t        j                         }t        j                  | j	                         g ||t        d      z
  |      }d|v sJ y)u'   stale 없을 때 '해당 없음' 표시rA   r5   u   (해당 없음)Nr   r   s      r   (test_stale_section_shows_none_when_emptyz8TestBuildReport.test_stale_section_shows_none_when_empty   sF    lln!3!3!5r3iUVFW@WY\] F***r   r(   )r*   r+   r,   r-   r   rQ   r   r   r   r   r   r   r.   r   r   r{   r{      s-    '
tCH~ 
88(%+r   r{   c                   (    e Zd ZdZddZddZddZy)TestWeekPeriodCalculationu-   main()의 전주 월~일 기간 계산 검증Nc                    ddl m} |j                  t        dt	        dddddd            5  t	        dddddd      }|j                         }|t        |j                         	      z
  }|t        d
	      z
  }|t        d	      z
  }t	        j                  |t        j                  j                               }t	        j                  |t        j                  j                               }ddlm}	 | |	ddd      k(  sJ | |	ddd      k(  sJ |t	        dddddd      k(  sJ |j                          |	ddd      k(  sJ |j                  dk(  sJ |j                  dk(  sJ 	 ddd       y# 1 sw Y   yxY w)u*   월요일 실행 시 전주 월~일 기간r   )patch	now_localr   r`         )return_valuer5   rA   rB   date         ;   N)unittest.mockr   objectr   r   r   r   weekdaycombinemintimemaxhourminute)
r   r   r;   todaythis_mondayprev_mondayprev_sundaysinceuntilr   s
             r   'test_monday_execution_returns_prev_weekzATestWeekPeriodCalculation.test_monday_execution_returns_prev_week   s^    	(\\"kq"aQRTU8V\W 	&4B1a0CHHJE)"AAK%	q(99K%	q(99K$$[(,,2C2C2EFE$$[(,,2C2C2EFE%$tQ"3333$tQ"3333HT1b!Q::::::<4a#4444::###<<2%%%!	& 	& 	&s   D8E//E8c                    t        dddddd      }|j                         }|t        |j                               z
  }|t        d      z
  }|t        d	      z
  }dd
l m} | |ddd      k(  sJ | |ddd      k(  sJ y)u6   수요일 실행해도 동일한 전주 월~일 기간r   r`   r         r   r5   rA   rB   r   r   r   N)r   r   r   r   )r   r;   r   r   r   r   r   s          r   /test_wednesday_execution_returns_same_prev_weekzITestWeekPeriodCalculation.test_wednesday_execution_returns_same_prev_week   s    tQBA.
iU]]_==!I1$55!I1$55!d4B////d4B////r   c           	          t        dddddd      }d}|}|t        |      z
  }|t        dddddd      k(  sJ ||k(  sJ y	)
u9   --days 옵션 지정 시 기존 방식(now - N일) 사용r   r`   r   r   r   r   r5      Nr   )r   r;   r6   r   r   s        r   +test_days_option_overrides_week_calculationzETestWeekPeriodCalculation.test_days_option_overrides_week_calculation  sX    tQAq!,iT**q!Q15555||r   r(   )r*   r+   r,   r-   r   r   r   r.   r   r   r   r      s    7&,
0r   r   )r-   importlib.util	importlibjsonsysr   r   pathlibr   typingr   r   r	   pytestutilspec_from_file_location__file__parent_specloadermodule_from_specr   __annotations__exec_moduler   r0   rT   r{   r   r.   r   r   <module>r      s      
 (  " "  	..N  #55	 U\\5 55
..
)
)%
0C 0    1 1>     FM- M-`7+ 7+t, ,r   