
    iGD                     R	   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ddlZddlmZ ddlmZ ddlmZmZ ddlZ ee
j*                  j-                  dd            Zedz  Zd	ej2                  vr@ e       Z e       ej6                  _         e       ej2                  d
<   eej2                  d	<   ej:                  j=                  d ee            Z g Z!dZ"e e"uZ#e#Z$e#re jJ                  Z&dZ'e&e'uZ(e(Z$e$sB ejR                  de#fde e"f      d ejT                         v s ejV                  e       r ejX                  e       nd ejX                  e"      dz  Z-dde-iz  Z.e!j_                  e.       e#r ejR                  de(fde&e'f      d ejT                         v s ejV                  e       r ejX                  e       nd ejX                  e&       ejX                  e'      dz  Z0dde0iz  Z1e!j_                  e1        ejd                  e!d      i z  Z3dde3iz  Z4 e5 ejl                  e4            dxZ$xZ!xZ#xZ"xZ&xZ(Z'ej:                  jo                  e       Z8e jJ                  js                  e8       e8jt                  Z:edz  Z;ej:                  j=                  d ee;            Z<g Z!dZ"e<e"uZ#e#Z$e#re<jJ                  Z&dZ'e&e'uZ(e(Z$e$sB ejR                  de#fde<e"f      d ejT                         v s ejV                  e<      r ejX                  e<      nd ejX                  e"      dz  Z-dde-iz  Z.e!j_                  e.       e#r ejR                  de(fde&e'f      d ejT                         v s ejV                  e<      r ejX                  e<      nd ejX                  e&       ejX                  e'      dz  Z0dde0iz  Z1e!j_                  e1        ejd                  e!d      i z  Z3dde3iz  Z4 e5 ejl                  e4            dxZ$xZ!xZ#xZ"xZ&xZ(Z'ej:                  jo                  e<      Z=e<jJ                  js                  e=       e=j|                  Z>dede:fdZ?dede>fdZ@ G d d       ZA G d! d"      ZBd#eCdeCfd$ZDd%ed#eCddfd&ZE G d' d(      ZFy))u  
test_task_timer_qc.py - task-timer qc_result 필드 + 히스토리 API 테스트

테스트 항목:
1. test_end_task_with_qc_result_pass: end_task에 qc_result="PASS" 전달 → task_data에 기록
2. test_end_task_without_qc_result: end_task에 qc_result 미전달 → task_data에 qc_result=None
3. test_end_task_with_qc_result_fail: end_task에 qc_result="FAIL" 전달 → task_data에 기록
4. test_end_task_with_qc_result_warn: end_task에 qc_result="WARN" 전달 → task_data에 기록
5. test_cli_end_with_qc_result: CLI end --qc-result PASS → 정상 동작
6. test_get_history_stats_completed_only: completed 작업만 집계
7. test_get_history_stats_team_classification: 팀별 분류 정확
8. test_get_history_stats_qc_pass_rate: QC 통과율 계산 정확
9. test_get_history_stats_empty: 데이터 없을 때 빈 dict 반환
10. test_get_history_stats_avg_duration: 평균 소요시간 계산 정확
    N)datetime)Path)	MagicMockpatchWORKSPACE_ROOTz/home/jay/workspacezmemory/task-timer.pyzutils.loggerutils
task_timer)is not)z%(py2)s is not %(py5)sspec)py2py5z%(py7)spy7)z5%(py11)s
{%(py11)s = %(py9)s.loader
} is not %(py14)s)py9py11py14z%(py16)spy16zassert %(py19)spy19zdashboard/server.pydashboard_serverspec2tmp_pathreturnc                     | dz  j                  dd       | dz  dz  j                  dd       | dz  dz  j                  dd       t        t        |             S )u8   임시 디렉토리 기반 TaskTimer 인스턴스 생성memoryTparentsexist_okeventsdaily)workspace_path)mkdir	TaskTimerstrr   s    //home/jay/workspace/tests/test_task_timer_qc.py
make_timerr%   ?   sc    t<8#**4$*G7"))$)FCM22    c                 D    | dz  j                  dd       t        |       S )u9   임시 디렉토리 기반 DataLoader 인스턴스 생성r   Tr   )r    
DataLoaderr#   s    r$   make_data_loaderr)   G   s%    t<hr&   c                   6    e Zd Zd Zd Zd Zd Zd Zd Zd Z	y)	TestEndTaskQcResultc                    t        |      }|j                  ddd       |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}}|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)uH   end_task에 qc_result='PASS' 전달 → task_data['qc_result'] == 'PASS'ztask-792	dev1-teamu   QC 테스트PASS	qc_resultstatus	completed==z%(py1)s == %(py4)spy1py4assert %(py6)spy6Ntasksr0   )	r%   
start_taskend_task
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanationtimers)
selfr   timerresult@py_assert0@py_assert3@py_assert2@py_format5@py_format7	task_datas
             r$   !test_end_task_with_qc_result_passz5TestEndTaskQcResult.test_end_task_with_qc_result_passS   s    8$[.A
f=h.;.;....;......;.......LL)*5	%//%////%///%//////////r&   c                    t        |      }|j                  ddd       |j                  d       |j                  d   d   }|d   }d}||u }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      d	z  }d
d|iz  }t        t	        j                  |            dx}x}}y)uB   end_task에 qc_result 미전달 → task_data['qc_result'] == Noneztask-793r-   u   QC 없는 테스트r;   r0   Nisz%(py1)s is %(py4)sr6   r9   r:   	r%   r<   r=   rC   r>   r?   r@   rA   rB   	rD   r   rE   rL   rG   rH   rI   rJ   rK   s	            r$   test_end_task_without_qc_resultz3TestEndTaskQcResult.test_end_task_without_qc_result]   s    8$[2GHz"LL)*5	%--%----%---%----------r&   c                    t        |      }|j                  ddd       |j                  dd       |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)uH   end_task에 qc_result='FAIL' 전달 → task_data['qc_result'] == 'FAIL'ztask-794	dev2-teamu   FAIL 테스트FAILr/   r;   r0   r3   r5   r6   r9   r:   NrR   rS   s	            r$   !test_end_task_with_qc_result_failz5TestEndTaskQcResult.test_end_task_with_qc_result_failf       8$[2BCzV4LL)*5	%//%////%///%//////////r&   c                    t        |      }|j                  ddd       |j                  dd       |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)uH   end_task에 qc_result='WARN' 전달 → task_data['qc_result'] == 'WARN'ztask-795	dev3-teamu   WARN 테스트WARNr/   r;   r0   r3   r5   r6   r9   r:   NrR   rS   s	            r$   !test_end_task_with_qc_result_warnz5TestEndTaskQcResult.test_end_task_with_qc_result_warno   rY   r&   c                    t        |      }|j                  ddd       |j                  dd       |j                  d   d   }|d   }d}||u }|slt	        j
                  d	|fd
||f      t	        j                  |      t	        j                  |      dz  }dd|iz  }t        t	        j                  |            dx}x}}y)uR   end_task에 qc_result='' (빈 문자열) 전달 → task_data['qc_result'] == Noneztask-796r-   u   빈 문자열 테스트 r/   r;   r0   NrO   rQ   r6   r9   r:   rR   rS   s	            r$   $test_end_task_empty_string_qc_resultz8TestEndTaskQcResult.test_end_task_empty_string_qc_resultx   s    8$[2KLzR0LL)*5	%--%----%---%----------r&   c                 <   t        |      }|j                  ddd       |j                  dd       |dz  dz  }|j                  } |       }|sdd	t	        j
                         v st        j                  |      rt        j                  |      nd	t        j                  |      t        j                  |      d
z  }t        t        j                  |            dx}}t        |d      5 }t        j                  |      }ddd       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# 1 sw Y   xY w)u?   end_task 후 task-timers.json에 qc_result 저장 여부 확인ztask-797r-   u   JSON 저장 테스트r.   r/   r   task-timers.jsonzAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}
timer_file)py0r   r8   Nutf-8encodingr;   r0   r3   r5   r6   r9   r:   )r%   r<   r=   exists@py_builtinslocalsr>   _should_repr_global_namer@   rA   rB   openjsonloadr?   )rD   r   rE   rc   @py_assert1rH   rJ   fdatarG   rI   rK   s               r$   )test_end_task_qc_result_persisted_in_jsonz=TestEndTaskQcResult.test_end_task_qc_result_persisted_in_json   s(   8$[2IJzV4 (+==
  " """"""""z"""z""" """"""""""*w/ 	 199Q<D	 G}Z(5??5????5???5??????????	  	 s   -FFc                    t        |      }|j                  ddd       |j                  dd       |j                  dd      }|j                  }d} ||      }d}||u }|st	        j
                  d	|fd
||f      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      t	        j                  |      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}x}x}}|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)u`   이미 completed 태스크 재호출 → already_completed 반환, qc_result 덮어쓰기 없음ztask-798r-   u   멱등성 테스트r.   r/   rW   already_completedTrO   )zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)srF   )rd   r   r8   r:   r   zassert %(py11)sr   Nr;   r0   r3   r5   r6   r9   r:   )r%   r<   r=   getr>   r?   ri   rj   rk   r@   rA   rB   rC   )rD   r   rE   rF   ro   rH   @py_assert5@py_assert8@py_assert7@py_format10@py_format12rG   rI   rJ   rK   s                  r$   *test_end_task_idempotent_already_completedz>TestEndTaskQcResult.test_end_task_idempotent_already_completed   s;   8$[2GHzV4 
f=zz6-6z-.6$6.$6666.$666666v666v666z666-666.666$6666666||G$Z0=GG=GGGG=GGG=GGGGGGGGGGr&   N)
__name__
__module____qualname__rM   rT   rX   r]   r`   rr   r{    r&   r$   r+   r+   R   s'    0.00.@
Hr&   r+   c                       e Zd Zd Zd Zy)TestCliQcResultc           
         t        j                  t        j                  t	        t
              ddddgddi t        d      j                  dt	        |      i      }|j                  }d	}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d|j                          dz   d|iz  }t#        t        j$                  |            dx}x}}t        j                  t        j                  t	        t
              ddddgddi t        d      j                  dt	        |      i      }|j                  }d	}||k(  }|st        j                  d
|fd||f      dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        j                  d|j                          dz   d|iz  }t#        t        j$                  |            dx}x}}t'        j(                  |j*                        }	|	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z  dz  }t-        |d       5 }t'        j.                  |      }ddd       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# 1 sw Y   xY w)#uL   CLI: python3 task-timer.py end task-792.1 --qc-result PASS → 정상 실행startz
task-792.1--teamr-   Tosr   capture_outputtextenvr   r3   z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sresult_startrd   r   r   u   start 실패: z
>assert %(py7)sr   Nendz--qc-resultr.   
result_endu   end 실패: r1   r2   r5   r6   r9   r:   r   rb   re   rf   r;   r0   )
subprocessrunsys
executabler"   _TIMER_PATH
__import__environ
returncoder>   r?   ri   rj   rk   r@   _format_assertmsgstderrrA   rB   rm   loadsstdoutrl   rn   )rD   r   r   ro   @py_assert4rH   @py_format6@py_format8r   outrG   rI   rJ   rK   rc   rp   rq   s                    r$    test_cli_end_with_qc_result_passz0TestCliQcResult.test_cli_end_with_qc_result_pass   s    "~~K   M:d#++M-=s8}M
 &&S!S&!+SSS&!SSSSSS|SSS|SSS&SSS!SSS~l>Q>Q=R-SSSSSSSS  ^^K   M:d#++M-=s8}M

 $$MM$)MMM$MMMMMMzMMMzMMM$MMMMMM\*:K:K9L+MMMMMMMMjj**+8}++}++++}+++}++++++++++ (+==
*w/ 	 199Q<D	 G}\*;7A6A76AAAA76AAA7AAA6AAAAAAA	  	 s   O((O1c           
         t        j                  t        j                  t	        t
              ddddgddi t        d      j                  dt	        |      i       t        j                  t        j                  t	        t
              d	dgddi t        d      j                  dt	        |      i      }|j                  }d
}||k(  }|st        j                  d|fd||f      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z  dz  }t#        |d      5 }	t%        j&                  |	      }
ddd       
d   d   d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                   |            dx}x}}y# 1 sw Y   xY w)uQ   CLI: python3 task-timer.py end task-792.2 (--qc-result 없이) → qc_result=Noner   z
task-792.2r   r-   Tr   r   r   r   r   r3   r   r   r   zassert %(py7)sr   Nr   rb   re   rf   r;   r0   rO   rQ   r6   r9   r:   )r   r   r   r   r"   r   r   r   r   r>   r?   ri   rj   rk   r@   rA   rB   rl   rm   rn   )rD   r   r   ro   r   rH   r   r   rc   rp   rq   rG   rI   rJ   rK   s                  r$   test_cli_end_without_qc_resultz.TestCliQcResult.test_cli_end_without_qc_result   s    	^^S-whP[\M:d#++M-=s8}M		
  ^^^^S-ulCM:d#++M-=s8}M	

 $$))$))))$))))))z)))z)))$))))))))))(+==
*w/ 	 199Q<D	 G}\*;7?4?74????74???7???4???????	  	 s   H88IN)r|   r}   r~   r   r   r   r&   r$   r   r      s    (BT@r&   r   r;   c                 
    d| iS )u%   task-timers.json 구조 생성 헬퍼r;   r   )r;   s    r$   _build_task_timersr      s    Ur&   pathc                     | j                  dd       t        | dz  dd      5 }t        j                  t	        |      |d       d	d	d	       y	# 1 sw Y   y	xY w)
u   task-timers.json 파일 쓰기Tr   rb   wre   rf   F)ensure_asciiN)r    rl   rm   dumpr   )r   r;   rp   s      r$   _write_task_timersr      sU    JJtdJ+	d''w	? D1		$U+QUCD D Ds   "AAc                   B    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zy
)TestGetHistoryStatsc                    dddddddddddddddd	}t        |d
z  |       t        |      }|j                          |j                         }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   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)uC   get_history_stats: completed 작업만 집계, running/stale 제외r-   r2   r.   g      ^@team_idr1   r0   duration_secondsrunningNstale)ztask-1ztask-2ztask-3r   inz%(py1)s in %(py3)sstatsr7   py3assert %(py5)sr   total_tasks   r3   r5   r6   r9   r:   qc_passr   r)   
load_tasksget_history_statsr>   r?   r@   ri   rj   rk   rA   rB   rD   r   r;   loaderr   rG   rI   @py_format4r   rH   rJ   rK   s               r$   test_completed_onlyz'TestGetHistoryStats.test_completed_only   s    '%#$)	 '#!$(	 '!!$(	
( 	8h.6!(+((* #{e####{e###{######e###e#######[!-05A50A55550A5550555A5555555[!),11,1111,111,1111111111r&   c                 N   ddddddddddddd	d
dd}t        |dz  |       t        |      }|j                          |j                         }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   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   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'   get_history_stats: 팀별 분류 정확r-   r2   r.         N@r   rV   rW        V@r\   g      >@)ztask-10ztask-11ztask-12r   r   r   r   r   r   r   Nr   r   r3   r5   r6   r9   r:      qc_failqc_warnr   r   s               r$   test_team_classificationz,TestGetHistoryStats.test_team_classification  s    '%#$(	 '%#$(	 '%#$(	
( 	8h.6!(+((*#{e####{e###{######e###e########{e####{e###{######e###e#######[!-05A50A55550A5550555A5555555[!-05A50A55550A5550555A5555555[!),11,1111,111,1111111111[!),11,1111,111,1111111111r&   c                    dddddddddddddddddd	d
dd}t        |dz  |       t        |      }|j                          |j                         }|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}||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}||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}||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
}||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-   get_history_stats: QC 통과율 계산 정확r-   r2   r.         Y@r         i@rW   g     b@Ng      I@)ztask-20ztask-21ztask-22ztask-23r   r      r3   r5   r6   r9   r:   r   r   r   r   qc_noneqc_pass_rate	r   r)   r   r   r>   r?   r@   rA   rB   rD   r   r;   r   r   srG   rH   rI   rJ   rK   s              r$   test_qc_pass_ratez%TestGetHistoryStats.test_qc_pass_rate:  s"    '%#$)	 '%#$)	 '%#$)	 '%!$(	'
4 	8h.6!(+((*+$1$1$$$$1$$$$$$1$$$$$$$| q |q    |q   |   q       | q |q    |q   |   q       | q |q    |q   |   q        (D( D(((( D((( (((D(((((((r&   c                    t        |dz  i        t        |      }|j                          |j                         }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)	u7   get_history_stats: 데이터 없을 때 빈 dict 반환r   r3   )z%(py0)s == %(py3)sr   )rd   r   r   r   N)r   r)   r   r   r>   r?   ri   rj   rk   r@   rA   rB   )rD   r   r   r   rI   ro   r   r   s           r$   test_empty_dataz#TestGetHistoryStats.test_empty_datad  s    8h.3!(+((*u{uuur&   c                    ddddddddddd}t        |dz  |       t        |      }|j                          |j                         }|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)u4   get_history_stats: 평균 소요시간 계산 정확r[   r2   r.   r   r   g     r@)ztask-30ztask-31r   avg_duration_secondsr   r3   r5   r6   r9   r:   Nr   r   s              r$   test_avg_durationz%TestGetHistoryStats.test_avg_durationn  s     '%#$)	 '%#$)	
 	8h.6!(+((*+'(1E1(E1111(E111(111E1111111r&   c                    ddddddi}t        |dz  |       t        |      }|j                          |j                         }|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)u3   get_history_stats: avg_duration_human 포맷 확인ztask-40r-   r2   r.   r   r   r   avg_duration_humanu
   1분 30초r3   r5   r6   r9   r:   Nr   r   s              r$   test_avg_duration_human_formatz2TestGetHistoryStats.test_avg_duration_human_format  s     &%#$(	
 	8h.6!(+((*+%&6,6&,6666&,666&666,6666666r&   c                    ddddddddddd}t        |dz  |       t        |      }|j                          |j                         }|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}||k(  }|slt	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}}y)uP   get_history_stats: duration_seconds=None 태스크는 평균 계산에서 제외r-   r2   r.   Nr   r   )ztask-50ztask-51r   r   r   r3   r5   r6   r9   r:   r   r   r   r   s              r$   test_no_duration_tasksz*TestGetHistoryStats.test_no_duration_tasks  s    '%#$(	 '%#$)	
 	8h.6!(+((*+$1$1$$$$1$$$$$$1$$$$$$$'(1E1(E1111(E111(111E1111111r&   c                    ddddddi}t        |dz  |       t        |      }|j                          |j                         }|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}||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}||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}||k(  }|slt	        j
                  d
|fd||f      t	        j                  |      t	        j                  |      dz  }	dd|	iz  }
t        t	        j                  |
            dx}x}}y)uC   get_history_stats: qc_result=None 태스크는 qc_none으로 집계ztask-60r-   r2   Nr   r   r   r   r   r3   r5   r6   r9   r:   r   r   r   r   r   r   s              r$   test_qc_none_countz&TestGetHistoryStats.test_qc_none_count  s    &%!$(	
 	8h.6!(+((*+| q |q    |q   |   q       | q |q    |q   |   q       | q |q    |q   |   q       | q |q    |q   |   q       r&   c                    dddddi}t        |dz  |       t        |      }|j                          |j                         }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   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)uI   get_history_stats: team_id 없는 태스크는 'unknown' 팀으로 집계ztask-70r2   r.   r   )r1   r0   r   r   unknownr   r   r   r   r   r   Nr   r   r3   r5   r6   r9   r:   r   r   s               r$   test_unknown_team_idz(TestGetHistoryStats.test_unknown_team_id  s    %#$(
 	8h.6!(+((*!yE!!!!yE!!!y!!!!!!E!!!E!!!!!!!Y.3!3.!3333.!333.333!3333333r&   N)r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r&   r$   r   r      s2    2B!2F()T247&26!,4r&   r   )G__doc__builtinsri   _pytest.assertion.rewrite	assertionrewriter>   importlib.util	importlibrm   r   r   r   tempfiler   pathlibr   unittest.mockr   r   pytestr   ru   
_WORKSPACEr   modules_mock_logger
get_loggerreturn_valueutilspec_from_file_locationr"   r   ro   r   rH   rG   r   @py_assert10@py_assert13@py_assert12r?   rj   rk   r@   r   r   append@py_format15@py_format17_format_boolop@py_format18@py_format20rA   rB   module_from_spectask_timer_modexec_moduler!   _SERVER_PATHr   dashboard_modr(   r%   r)   r+   r   dictr   r   r   r   r&   r$   <module>r     sW        	  
    *  "**..!13HIJ
11 $;L+4;L($;CKK".CKK ~~--lC<LM 34 3t4 3DKK 3t 3Kt3 3 3 3t4 3 3 3 3 3t 3 3 3t 3 3 34 3 3 3 3 3 3 3Kt 3 3 3 3 3D 3 3 3D 3 3 3K 3 3t 3 3 3 3 3 3 3 3 3 3 3 3 3006    '$$	 11../A3|CTU 5D 5uD 5U\\ 5 5\5 5 5 5uD 5 5 5 5 5u 5 5 5u 5 5 5D 5 5 5 5 5 5 5\ 5 5 5 5 5U 5 5 5U 5 5 5\ 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5//6    '%%
3 3) 3 t  
  FH FH\A@ A@Rd t 
DT D$ D4 Dh4 h4r&   