
    (<i!                        d 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	m
Z
 ej                  j                  d e ee      j                  j                  j                  j                               ddlmZmZmZ  G d dej(                        Z G d d	ej(                        Z G d
 dej(                        Zedk(  r ej2                          yy)u3   test_skill_executor.py - TDD 테스트 (RED 단계)    N)Path)	MagicMockpatch)execute_skillload_env_key
load_skillc                   0    e Zd ZdZddZddZddZddZy)TestLoadEnvKeyu   load_env_key() 테스트Nc                     t        j                  t        j                  ddi      5  t	        d      }| j                  |d       ddd       y# 1 sw Y   yxY w)u!   환경변수에서 API 키 로드ANTHROPIC_API_KEYztest-key-from-envN)r   dictosenvironr   assertEqual)selfresults     _/home/jay/workspace/.worktrees/task-2057-dev2/scripts/autoresearch/tests/test_skill_executor.py#test_load_from_environment_variablez2TestLoadEnvKey.test_load_from_environment_variable   sL    ZZ

%8:M$NO 	:!"56FV%89	: 	: 	:s   AAc           	          t        j                  t        j                  i d      5  t        j                  j	                         D ci c]  \  }}|dk7  s|| }}}t        j                  t        j                  |d      5  t        dt
              5  | j                  t              5  t        d       ddd       ddd       ddd       ddd       yc c}}w # 1 sw Y   (xY w# 1 sw Y   ,xY w# 1 sw Y   0xY w# 1 sw Y   yxY w)u(   키가 없으면 EnvironmentError 발생Tclearr   zbuiltins.open)side_effectN)	r   r   r   r   itemsFileNotFoundErrorassertRaisesEnvironmentErrorr   )r   kvenv_without_keys       r   test_raises_if_not_foundz'TestLoadEnvKey.test_raises_if_not_found   s    ZZ

Bd3 	:02

0@0@0B_1aK^F^q!t_O_BJJtD :?8IJ :**+;< :$%89:::	: 	:_: :: :: :	: 	:sk   "D	CC)DC8C,-C 	9C,C8	DD C)%C,,C51C88D	=DDc           	         d}t        j                  t        j                  i d      5  t        j                  j	                         D ci c]  \  }}|dk7  s|| }}}t        j                  t        j                  |d      5  t        j                         5 }t        |      dz  }|j                  |       t        d      5 }	 ddd       ddd       ddd       ddd       t        j                  t        j                  dd	i      5  t        d      }| j                  |d	       ddd       yc c}}w # 1 sw Y   txY w# 1 sw Y   xxY w# 1 sw Y   |xY w# 1 sw Y   xY w# 1 sw Y   yxY w)
u5   환경변수 없을 때 .env.keys 파일에서 로드z(ANTHROPIC_API_KEY=test-key-from-envkeys
Tr   r   	.env.keysz(scripts.autoresearch.skill_executor.PathNMY_TEST_KEYzmy-value)r   r   r   r   r   tempfileTemporaryDirectoryr   
write_textr   r   )	r   env_contentr   r   r   tmpdirenv_keys_pathmock_path_clsr   s	            r   test_load_from_env_keys_filez+TestLoadEnvKey.test_load_from_env_keys_file%   s@   AZZ

Bd3 
	02

0@0@0B_1aK^F^q!t_O_BJJtD 002 f$(L;$>M!,,[9IJ m 	
	 ZZ

]J$?@ 	1!-0FVZ0	1 	1 ` 	  
	 
		1 	1sw   "E D6D6)E E+ED<		EEE E,6E <EEEEE	E  E),E5c                    t        j                         5 }t        |      dz  }|j                  d       t	        j
                  t        j                  i d      5  t	        dt        |            5  t        d      }| j                  |d       d	d	d	       d	d	d	       d	d	d	       y	# 1 sw Y   xY w# 1 sw Y   xY w# 1 sw Y   y	xY w)
u8   export 접두사가 있는 .env.keys 파일에서 로드r"   z$export MY_EXPORT_KEY=exported-value
Tr   z,scripts.autoresearch.skill_executor.Path.cwd)return_valueMY_EXPORT_KEYzexported-valueN)
r$   r%   r   r&   r   r   r   r   r   r   )r   r(   r)   r   s       r   &test_load_from_file_with_export_prefixz5TestLoadEnvKey.test_load_from_file_with_export_prefix8   s    ((* 
	?f L;6M$$%LMBJJ$7 ?B!%f ? */:F$$V-=>??	
	? 
	?
? ?? ?	
	? 
	?s<   ACB52B)B5C)B2.B55B>	:CC
returnN)__name__
__module____qualname____doc__r   r    r+   r/        r   r
   r
      s    ":	:1&?r7   r
   c                   T    e Zd ZdZddZdededdfdZddZdd	Zdd
Z	ddZ
ddZy)TestLoadSkillu   load_skill() 테스트r1   Nc                 X    t        j                         | _        | j                  | _        y )N)r$   mkdtempr(   
skills_dirr   s    r   setUpzTestLoadSkill.setUpJ   s    &&(++r7   
skill_namecontentc                     t        | j                        |z  }|j                  dd       |dz  j                  |       y )NT)parentsexist_okzSKILL.md)r   r<   mkdirr&   )r   r?   r@   	skill_dirs       r   _create_skill_filez TestLoadSkill._create_skill_fileN   s8    )J6	t4	Z	++G4r7   c                     d}| j                  d|       t        d| j                        \  }}| j                  d|       | j                  d|       | j                  d|       | j                  d|       y)	u@   프론트매터와 본문이 올바르게 분리되는지 확인us   ---
name: test-skill
description: "테스트 스킬"
---

# 테스트 스킬 본문

이것은 테스트입니다.
z
test-skillr<   zname: test-skillzdescription:u   # 테스트 스킬 본문u   이것은 테스트입니다.N)rF   r   r<   assertInr   r@   frontmatterbodys       r    test_load_skill_with_frontmatterz.TestLoadSkill.test_load_skill_with_frontmatterS   sk     	g6&|PT(+6nk21485t<r7   c                     d}| j                  d|       t        d| j                        \  }}| j                  d|       y)uA   본문에 프론트매터 구분자가 포함되지 않아야 함u0   ---
name: my-skill
---

# 본문 시작
내용.
zmy-skillrH   zname: my-skillN)rF   r   r<   assertNotInrJ   s       r   'test_load_skill_frontmatter_not_in_bodyz5TestLoadSkill.test_load_skill_frontmatter_not_in_bodyf   sC     	
G4&zdooNT 	)40r7   c                     d}| j                  d|       t        d| j                        \  }}| j                  |d       | j	                  d|       y)u$   프론트매터 없는 경우 처리u9   # 프론트매터 없는 스킬

본문만 있습니다.
zno-fm-skillrH    u   # 프론트매터 없는 스킬N)rF   r   r<   r   rI   rJ   s       r   #test_load_skill_without_frontmatterz1TestLoadSkill.test_load_skill_without_frontmatteru   sO     	w7&}QTb)7>r7   c                     | j                  t              5  t        d| j                         ddd       y# 1 sw Y   yxY w)u/   존재하지 않는 스킬은 FileNotFoundErrorznonexistent-skillrH   N)r   r   r   r<   r=   s    r   test_load_skill_file_not_foundz,TestLoadSkill.test_load_skill_file_not_found   s9    01 	H*tG	H 	H 	Hs	   7A c                     d}| j                  d|       t        d| j                        }| j                  |t               | j                  t        |      d       | j                  |d   t               | j                  |d   t               y)u0   반환값이 tuple[str, str] 형식인지 확인z---
name: t
---
bodytrH      r      N)rF   r   r<   assertIsInstancetupler   lenstr)r   r@   r   s      r   test_load_skill_returns_tuplez+TestLoadSkill.test_load_skill_returns_tuple   ss    +W-CDOO<fe,Va(fQi-fQi-r7   r0   )r2   r3   r4   r5   r>   r]   rF   rM   rP   rS   rU   r^   r6   r7   r   r9   r9   G   s>     &5S 53 54 5
=&1
?H
.r7   r9   c                       e Zd ZdZ ed      deddfd       Z ed      deddfd       Z ed      deddfd       Z ed      deddfd	       Z	y)
TestExecuteSkillu.   execute_skill() 테스트 - call_claude 모킹z/scripts.autoresearch.skill_executor.call_claudemock_call_clauder1   Nc                     d|_         t        ddd      }| j                  d|d          | j                  |d   d       | j                  |d	   d       | j	                  |d
   d       | j                  d|       y)u!   성공적인 호출 결과 반환u   결과 텍스트u   # 스킬 본문u   테스트 입력claude-sonnet-4-6
skill_body
test_inputmodeloutputinput_tokensr   output_tokensrg   errorN)r-   r   rI   assertGreaterr   rO   r   ra   r   s      r   test_execute_skill_successz+TestExecuteSkill.test_execute_skill_success   s     );%()%
 	(&*:;6.1156/2A6*=>&)r7   c                 V    d|_         t        ddd       |j                  ddd       y)u6   call_claude 호출 파라미터가 올바른지 확인   결과z# system promptz
user inputrc   rd   )promptrg   systemN)r-   r   assert_called_once_with)r   ra   s     r   &test_execute_skill_calls_api_correctlyz7TestExecuteSkill.test_execute_skill_calls_api_correctly   s<     )1%(#%	
 	00%$ 	1 	
r7   c                 6   t        d      |_        t        ddd      }| j                  |d   d       | j	                  d|       | j	                  d|d          | j                  |d	   d
       | j                  |d   d
       | j                  |d   d       y)u2   RuntimeError 발생 시 에러 딕셔너리 반환u   API 연결 실패u   # 본문   입력rc   rd   rh   rR   rk   ri   r   rj   rg   N)RuntimeErrorr   r   r   rI   rm   s      r   !test_execute_skill_error_handlingz2TestExecuteSkill.test_execute_skill_error_handling   s     (44G'H$!%
 	)2.gv&)6'?;/30!4*=>r7   c                 X    d|_         t        ddd      }| j                  |d   d       y)u-   결과에 model 필드가 포함되어야 함rp   u   본문rv   zclaude-opus-4-6rd   rg   N)r-   r   r   rm   s      r   *test_execute_skill_returns_model_in_resultz;TestExecuteSkill.test_execute_skill_returns_model_in_result   s7     )1%#
 	*;<r7   )
r2   r3   r4   r5   r   r   rn   rt   rx   rz   r6   r7   r   r`   r`      s    8
<=*9 * * >*  <=
y 
UY 
 >
  <=?) ?PT ? >?" <=
=9 
=Y] 
= >
=r7   r`   __main__)r5   jsonr   sysr$   unittestpathlibr   unittest.mockr   r   pathinsertr]   __file__parent#scripts.autoresearch.skill_executorr   r   r   TestCaser
   r9   r`   r2   mainr6   r7   r   <module>r      s    9  	 
    * 3tH~,,33::AAB C W W3?X&& 3?lG.H%% G.TB=x(( B=J zHMMO r7   