
    Di                         d dl Zd dlmc mZ d dlZej                  j                  d d       d dl	m
Z
 dZg dZdZdZd Zd	 Zd
 Zd Zd Zd Zd Zd Zy)    Nz /home/jay/workspace/teams/shared)scenario_generatoru   task-100.1: 인증 모듈 리팩터링
- setup_auth.py의 세션 생성 로직을 분리
- JWT 토큰 만료 처리 개선
- 빈 UID 입력 시 예외 처리 추가
)zauth/setup_auth.pyzapi/auth_router.pyztests/test_auth.pyu-  ```yaml
- id: SC-GEN-task-100-001
  category: smoke
  target: ["auth/setup_auth.py"]
  type: subprocess
  steps:
    - action: "python3 -c 'import auth.setup_auth'"
      expect_contains: ""
  priority: must
  automatable: false
  description: "auth 모듈 임포트 확인"

- id: SC-GEN-task-100-002
  category: edge-case
  target: ["auth/setup_auth.py"]
  type: pytest
  steps:
    - action: "pytest tests/test_auth.py::test_empty_uid -v"
      expect_contains: "passed"
  priority: should
  automatable: false
  description: "빈 UID 처리 확인"
```
u  - id: SC-GEN-task-200-001
  category: smoke
  target: ["api/auth_router.py"]
  type: curl
  steps:
    - action: "curl -s http://localhost:8000/auth/ping"
      expect_contains: "ok"
  priority: must
  automatable: false
  description: "auth router ping 확인"
c                     t        j                  t        t        ddd      } d}t	        |       }||k  }d}||k  }|r|s/t        j                  d||fd|||f      t        j                  |      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  }t        j                  dt	        |        d      dz   d|iz  }t        t        j                  |            dx}x}x}x}}y)u6   level=3 입력 시 15~30개 시나리오 생성 확인   insuwikitask-100task_contentchanged_fileslevelprojecttask_id      <=r   z0%(py1)s <= %(py7)s
{%(py7)s = %(py4)s(%(py5)s)
}z0%(py7)s
{%(py7)s = %(py4)s(%(py5)s)
} <= %(py9)slen	scenariospy1py4py5py7py9u4   level=3이면 15~30개 시나리오여야 하지만    개 생성됨
>assert %(py11)spy11Nr    generate_scenarios_from_templateSAMPLE_TASK_CONTENTSAMPLE_CHANGED_FILESr   
@pytest_ar_call_reprcompare	_saferepr@py_builtinslocals_should_repr_global_name_format_assertmsgAssertionError_format_explanationr   @py_assert0@py_assert6@py_assert2@py_assert8@py_assert3@py_format10@py_format12s           D/home/jay/workspace/teams/shared/qc/tests/test_scenario_generator.py$test_generate_scenarios_level3_countr4   B   M   "CC(*I  Y 2% 2 2%   22                                 $&    ?s9~>Nm\         c                     t        j                  t        t        ddd      } d}t	        |       }||k  }d}||k  }|r|s/t        j                  d||fd|||f      t        j                  |      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  }t        j                  dt	        |        d      dz   d|iz  }t        t        j                  |            dx}x}x}x}}y)u6   level=4 입력 시 30~50개 시나리오 생성 확인   r   r   r   r   2   r   r   r   r   r   u4   level=4이면 30~50개 시나리오여야 하지만 r   r   r   Nr   r+   s           r3   $test_generate_scenarios_level4_countr:   P   r5   r6   c            	         t        j                  t        t        ddd      } t	        |       }d}||kD  }|st        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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}| D ]<  }|j                  }d} ||      }d}	||	u }
|
st        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  }t        j                  d|j                  d       d|j                  d       d      dz   d|iz  }t        t        j                  |            dx}x}x}x}
}	? y)u7   모든 생성 시나리오에 automatable: false 확인r   r   r   r   r   >z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)sr   r   py0r   py3py6/   시나리오가 1개 이상 생성되어야 함
>assert %(py8)spy8NautomatableF)is)zI%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.get
}(%(py4)s)
} is %(py9)ssc)r@   py2r   rB   r      시나리오 idu)   의 automatable이 False여야 하지만 u    값임r   r   r   r   r    r!   r   r"   r#   r%   r&   r'   r$   r(   r)   r*   get)r   r.   @py_assert5@py_assert4@py_format7@py_format9rH   @py_assert1r0   r/   @py_assert7r1   r2   s                r3   -test_generated_scenario_has_automatable_falserT   ^   s   "CC(*I y>PAP>APPP>APPPPPP3PPP3PPPPPPyPPPyPPP>PPPAPPPPPPPPPPP 
vv 	
m 	
vm$ 	
 	
$- 	
 	
 	
$ 	
 	
	6	
 	
   	
 	
 		  	
 	
 		  	
 	
 		 $ 	
 	
 		 % 	
 	
 		 ). 	
 	
  BFF4L>)RSUSYSYZgShRiipq	
 	
 	
 	
 	
 	

r6   c            	         g d} t        j                  t        t        ddd      }t	        |      }d}||kD  }|st        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  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}x}}|D ]  }| D ]  }||v }	|	st        j                  d|	fd||f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |      rt        j                  |      nddz  }
t        j                  d|j                  dd       d| d      dz   d|
iz  }t        t        j                  |            d}	  y)ul   각 시나리오에 필수 필드(id, category, target, type, steps, description, automatable) 존재 확인)rK   categorytargettypestepsdescriptionrF   r   r   r   r   r   r<   r>   r   r   r?   rC   rD   rE   Ninz%(py0)s in %(py2)sfieldrH   r@   rI   rJ   rK   ?u   에 필수 필드 'u   '가 없음
>assert %(py4)sr   rL   )required_fieldsr   r.   rN   rO   rP   rQ   rH   r^   rR   @py_format3@py_format5s               r3   &test_generated_scenario_yaml_structurere   n   s   aO"CC(*I y>PAP>APPP>APPPPPP3PPP3PPPPPPyPPPyPPP>PPPAPPPPPPPPPPP $ 	EB;  5B  v     I   v     I      tS 122EeWKX    	r6   c                     t        j                  d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  }t        j                  d
|        dz   d|iz  }t        t        j                  |            dx}}y)uA   project='insuwiki', task_id='task-100.1' → 출력 경로 확인r   
task-100.1z/tmp/test_base)r   r   base_dirz;/tmp/test_base/scenarios/insuwiki/generated/task-100.1.yaml==)z%(py0)s == %(py3)spath)r@   rA   u#   출력 경로가 예상과 다름: 
>assert %(py5)sr   N)r   get_output_pathr"   r#   r%   r&   r'   r$   r(   r)   r*   )rk   r.   rR   @py_format4@py_format6s        r3   test_output_path_generationrp      s    --!D
 Q 4PP  4P              Q    .dV4    r6   c                  ,   t        j                  t        t        ddd      } | D cg c]  }|j	                  d       }}t        |      }t        |      }t        |      }||k(  }|st        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                  |      dt        j                         v st        j                  t
              rt        j                  t
              n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	t        j                  |      t        j                  |      dz  }t        j                  d|D cg c]  }|j                  |      dkD  s| c}       dz   d|iz  }	t        t        j                   |	            dx}x}x}}yc c}w c c}w )u=   생성된 시나리오들의 id가 모두 고유한지 확인r   r   r   r   rK   ri   )zn%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py11)s
{%(py11)s = %(py5)s(%(py9)s
{%(py9)s = %(py6)s(%(py7)s)
})
}r   idsset)r@   r   rA   r   rB   r   r   r   u   중복 ID 발견:    z
>assert %(py13)spy13N)r   r   r    r!   rM   r   rs   r"   r#   r%   r&   r'   r$   r(   countr)   r*   )
r   rH   rr   r.   r/   @py_assert10rO   r2   x@py_format14s
             r3   test_duplicate_id_in_generatedrz      s   "CC(*I #,
,B266$<
,C
,s8 3s8 s8} 8}$   8}                                                   #     #    $    %    AA		!q0@aABC      -As   J6J
J
c                  Z   t        j                  t        t        d      } t	        | t
              }|s!t        j                  d      dz   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	}t        |       }d
}||kD  }|st        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  }t        j                  d      dz   d|iz  }t        t        j                  |            d	x}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  }	t        j                  d      dz   d|	iz  }
t        t        j                  |
            d	x}}t        D ]  }|| v }|st        j                  d|fd|| f      dt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  |       rt        j                  |       nddz  }t        j                  d| d      dz   d|iz  }t        t        j                  |            d	} y	) uW   빌드된 프롬프트에 변경 파일 목록과 task 내용이 포함되는지 확인r   )r	   r
   r   u&   프롬프트는 문자열이어야 함7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstancepromptstrr@   r   rI   r   Nr   r<   r>   r   r?   u*   프롬프트가 비어있지 않아야 함rD   rE   rg   r[   )z%(py1)s in %(py3)s)r   rA   u2   프롬프트에 task 내용이 포함되어야 함rl   r   r]   changed_filer_   u   프롬프트에 변경 파일 'u   '이 포함되어야 함ra   r   )r   build_promptr    r!   r}   r   r"   r(   r%   r&   r'   r$   r)   r*   r   r#   )r~   r0   rd   r.   rN   rO   rP   rQ   r,   rn   ro   r   rR   rc   s                 r3   "test_build_prompt_includes_changesr      s   ,,(*F
 fc"L"LL$LLLLLLL:LLL:LLLLLLfLLLfLLLLLLcLLLcLLL"LLLLLLv;HH;?HHH;HHHHHH3HHH3HHHHHHvHHHvHHH;HHHHHHHHHHHHHH W<6!WWW<6WWW<WWWWWW6WWW6WWWW#WWWWWWW - 
v% 	
 	
|v 	
 	
	6	
 	
   	
 	
 		  	
 	
	6	
 	
   & 	
 	
 		  & 	
 	
  .l^;ST	
 	
 	
 	
 	

r6   c                     t        j                  t              } t        | t              }|s!t        j                  d      dz   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}t        |       }d}||k(  }|st        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  }t        j                  dt        |        d      dz   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}}t        j                  t              }	t        |	t              }|s!t        j                  d      dz   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}t        |	      }d}||k(  }|st        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  }t        j                  dt        |	       d      dz   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}}t        j                  d      }
t        |
t              }|s!t        j                  d      dz   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}t        |
      }d}||k(  }|st        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  }t        j                  d       dz   d|iz  }t        t        j                  |            dx}x}}y)!uO   LLM 응답(YAML 문자열)을 파싱하여 시나리오 리스트 반환 확인u    반환값은 리스트여야 함r|   r}   r   listr   N   ri   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   r?   u/   2개 시나리오가 파싱되어야 하지만 u   개 반환됨rD   rE   r   rK   zSC-GEN-task-100-001)z%(py1)s == %(py4)s)r   r   zassert %(py6)srB   rt   zSC-GEN-task-100-002scenarios_plainu/   1개 시나리오가 파싱되어야 하지만 zSC-GEN-task-200-001zthis is not yaml: [[[u/   파싱 실패 시 리스트를 반환해야 함invalidu3   파싱 실패 시 빈 리스트를 반환해야 함)r   parse_llm_responseSAMPLE_LLM_YAML_RESPONSEr}   r   r"   r(   r%   r&   r'   r$   r)   r*   r   r#   SAMPLE_LLM_PLAIN_YAML_RESPONSE)r   r0   rd   r.   rN   rO   rP   rQ   r,   r   r   s              r3   "test_parse_llm_response_valid_yamlr      s    #556NOIi&J&JJ(JJJJJJJ:JJJ:JJJJJJiJJJiJJJJJJJJJJJJ&JJJJJJy>oQo>Qooo>Qoooooo3ooo3ooooooyoooyooo>oooQooo"QRUV_R`Qaan ooooooooQ<6!66!66666!6666666!66666666Q<6!66!66666!6666666!66666666 );;<Z[Oot,P,PP.PPPPPPP:PPP:PPPPPPoPPPoPPPPPPtPPPtPPP,PPPPPP{1{1${{{1{{{{{{3{{{3{{{{{{{{{{{{{{{1{{{(WX[\kXlWmmz&{{{{{{{{1d#<'<<#'<<<<<#'<<<<#<<<'<<<<<<<< !334KLGgt$W$WW&WWWWWWW:WWW:WWWWWWgWWWgWWWWWWtWWWtWWW$WWWWWWw<S1S<1SSS<1SSSSSS3SSS3SSSSSSwSSSwSSS<SSS1SSSSSSSSSSSr6   )builtinsr%   _pytest.assertion.rewrite	assertionrewriter"   sysrk   insertqcr   r    r!   r   r   r4   r:   rT   re   rp   rz   r   r    r6   r3   <module>r      sk      
 5 6 !
   4" "
 $	
(Tr6   