
    ˆj!                    B   d Z ddlm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mZ e
j                  j                  de	j                  j!                  e	j                  j#                  e                   ddlZddlmZmZmZmZ  ej2                  d      d        Z G d	 d
      Z G d d      Z G d d      Zd Zd Zd Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*ejV                  jY                  dg d      d        Z-d Z.d  Z/d! Z0d" Z1d# Z2d$ Z3d% Z4d& Z5y)'u  test_server.py - 아누 공용 임베딩 서비스 pytest.

검증 항목
- /health 응답 스키마
- /embed 가 정확히 768차원을 반환
- 결정론성: 같은 입력 → 같은 벡터
- 빈 입력/비문자열/배치초과 거부 (422)
- 차원 불변식 fail-closed: 768 이 아니면 500 (조용한 truncate/padding 금지)
- 모델이 서버 생애주기 동안 **1회만** 로드되는지
    )annotationsN)
TestClient)EMBEDDING_DIMMAX_BATCH_SIZEMAX_TEXT_CHARS
MODEL_NAMEmodule)scopec               #  p   K   t        t        j                        5 } |  ddd       y# 1 sw Y   yxY ww)uL   TestClient 를 context manager 로 사용 → lifespan(startup) 1회 실행.N)r   serverapp)test_clients    5/home/jay/workspace/services/embedding/test_server.pyclientr      s0      
FJJ	 ;  s   6*	636c                      e Zd ZdZddZd Zy)
_FakeModeluW   차원 위반을 재현하기 위한 가짜 모델 (정상 포맷의 잘못된 차원).c                    || _         y Ndim)selfr   s     r   __init__z_FakeModel.__init__$   s	        c                H    |D cg c]  }dg| j                   z   c}S c c}w Ng?r   r   textskwargs_s       r   encodez_FakeModel.encode'   s!    */0Q 000s   N)r   int)__name__
__module____qualname____doc__r   r     r   r   r   r   !   s    a1r   r   c                      e Zd Zd Zy)	_NaNModelc                N    |D cg c]  }t        d      gt        z   c}S c c}w )Nnan)floatr   r   s       r   r    z_NaNModel.encode,   s!    8=>1u.>>>s   "Nr"   r#   r$   r    r&   r   r   r(   r(   +   s    ?r   r(   c                      e Zd Zd Zy)_WrongCountModelc                    dgt         z  gS r   )r   )r   r   r   s      r   r    z_WrongCountModel.encode1   s    %&&r   Nr,   r&   r   r   r.   r.   0   s    'r   r.   c                F   | j                  d      }|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}}|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   }|t        k(  }	|	st        j                  d|	fd|t        f      t        j                  |      dt	        j
                         v st        j                  t              rt        j                  t              nddz  }dd|iz  }t        t        j                  |            d 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}||u }	|	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 )Nz/health   ==z3%(py2)s
{%(py2)s = %(py0)s.status_code
} == %(py5)sresppy0py2py5assert %(py7)spy7statusokz%(py1)s == %(py4)spy1py4assert %(py6)spy6modelz%(py1)s == %(py3)sr   r@   py3assert %(py5)sr9   	dimension   loadedTis)z%(py1)s is %(py4)sdevicecpu)getstatus_code
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationjsonr   )r   r5   @py_assert1@py_assert4@py_assert3@py_format6@py_format8body@py_assert0@py_assert2@py_format5@py_format7@py_format4s                r   test_health_okrf   :   s&   ::i D"s"s""""s""""""4"""4""""""s"""""""99;D>!T!>T!!!!>T!!!>!!!T!!!!!!!=&=J&&&&=J&&&=&&&&&&J&&&J&&&&&&&###################>!T!>T!!!!>T!!!>!!!T!!!!!!!>"U">U"""">U""">"""U"""""""r   c                 p   d} t         | k(  }|st        j                  d|fdt         | f      dt        j                         v st        j
                  t               rt        j                  t               ndt        j                  |       dz  }dd|iz  }t        t        j                  |            d x}} y )NrJ   r2   z%(py0)s == %(py3)sr   r7   rG   rH   r9   )	r   rR   rS   rT   rU   rV   rW   rX   rY   )rb   r[   re   r^   s       r   %test_health_dimension_is_768_constantrj   E   s[    =C=C==Cr   c                	   | j                  dddgdd      }|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}}|j                         }|d   }|t        k(  }	|	st        j                  d|	fd|t        f      t        j                  |      dt	        j
                         v st        j                  t              rt        j                  t              nddz  }
dd|
iz  }t        t        j                  |            d 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   }t        |      }d}||k(  }|st        j                  d|fd||f      dt	        j
                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }dd |iz  }t        t        j                  |            d x}x}x}}|d   D ]  }t        |      }	d}|	|k(  }|st        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  }d$d%|iz  }t        t        j                  |            d x}	x}}d& |D        }t        |      }|sd'd(t	        j
                         v st        j                  t              rt        j                  t              nd(t        j                  |      t        j                  |      d)z  }t        t        j                  |            d x}} y )*N/embedu   안녕하세요u   실손의료비 보장Tr   	normalizerZ   r1   r2   r4   r5   r6   r:   r;   rD   rE   r   rF   rH   r9   rI   rJ   r>   r?   rB   rC   
embeddings   z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)slenr7   r8   rA   r;   assert %(py9)spy9)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)svec)r7   r@   rG   rC   zassert %(py8)spy8c              3  <   K   | ]  }t        |t                y wr   )
isinstancer+   .0vs     r   	<genexpr>z4test_embed_returns_768_dimensions.<locals>.<genexpr>W   s     5A:a'5s   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}all)r7   r8   rA   )postrQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   r   rs   r   )r   r5   r[   r\   r]   r^   r_   r`   ra   rb   re   rc   rd   @py_assert6@py_assert5@py_format10rw   @py_format9s                     r   !test_embed_returns_768_dimensionsr   N   s   ;;x1BD\0]lp&q;rD"s"s""""s""""""4"""4""""""s"""""""99;D=&=J&&&&=J&&&=&&&&&&J&&&J&&&&&&&###################L!'3!"'a'"a''''"a''''''3'''3'''!'''"'''a'''''''L! 63x3x3x3ss33x3555s555555555s555s555555555555556r   c                x   | j                  ddgdd      }|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}}|j                         d   d   }t        d |D              dz  }d}	||	z
  }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                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}	x}x}
x}}y )Nrl   u   보험 특약 설명Trm   ro   r1   r2   r4   r5   r6   r:   r;   rp   r   c              3  &   K   | ]	  }||z    y wr   r&   r{   s     r   r~   z<test_embed_normalize_true_gives_unit_norm.<locals>.<genexpr>^        "q1u"         ?      ?-C6?<z;%(py6)s
{%(py6)s = %(py0)s((%(py1)s - %(py3)s))
} < %(py9)sabsnormr7   r@   rG   rC   rv   assert %(py11)spy11r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   sumr   r   r5   r[   r\   r]   r^   r_   rw   r   rb   r   @py_assert8@py_assert7r   @py_format12s                  r   )test_embed_normalize_true_gives_unit_normr   Z   sb   ;;x1G0HW[&\;]D"s"s""""s""""""4"""4""""""s"""""""
))+l
#A
&C"c""c)D!tcz!3z?!T!?T!!!!?T!!!!!!3!!!3!!!!!!t!!!t!!!c!!!?!!!T!!!!!!!!r   c                v   | j                  dddg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}}|j                         d   d   }t        d |D              dz  }d}	||	z
  }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                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}	x}x}
x}}y)u?   normalize 를 생략하면 기본 True 로 동작해야 한다.rl   r   u   기본값 확인ro   r1   r2   r4   r5   r6   r:   r;   Nrp   r   c              3  &   K   | ]	  }||z    y wr   r&   r{   s     r   r~   z7test_embed_normalize_default_is_true.<locals>.<genexpr>g   r   r   r   r   r   r   r   r   r   r   r   r   r   r   s                  r   $test_embed_normalize_default_is_truer   b   sa   ;;xw1C0D&E;FD"s"s""""s""""""4"""4""""""s"""""""
))+l
#A
&C"c""c)D!tcz!3z?!T!?T!!!!?T!!!!!!3!!!3!!!!!!t!!!t!!!c!!!?!!!T!!!!!!!!r   c                J   dgdd}| j                  d|      j                         d   d   }| j                  d|      j                         d   d   }||k(  }|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  }dd|iz  }t        t        j                  |            d }y )Nu#   결정론성 확인 문장입니다Trm   rl   ro   rp   r   r2   )z%(py0)s == %(py2)sfirstsecond)r7   r8   zassert %(py4)srA   )
r   rZ   rR   rS   rT   rU   rV   rW   rX   rY   )r   payloadr   r   r[   @py_format3rc   s          r   /test_embed_deterministic_same_input_same_vectorr   k   s    >?dSGKKwK/446|DQGE[[[0557EaHFF?5F55FFr   c                `   | j                  dddgdd      }|j                         d   }|d   }|d	   }||k7  }|slt        j                  d
|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }t        t        j                  |            d x}x}}y )Nrl   u   암 진단비u   자동차 보험료Trm   ro   rp   r      )!=)z%(py1)s != %(py4)sr?   rB   rC   )r   rZ   rR   rS   rW   rX   rY   )r   r5   vecsra   r]   rb   rc   rd   s           r   1test_embed_different_texts_give_different_vectorsr   r   s    ;;xBW0Xgk&l;mD99;|$D7d1g7g7g7gr   c                   dt         dz   z  }| j                  d|gdd      }|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}}|j                         d   d   }t        |      }d}||k(  }	|	st        j                  d|	fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      dz  }dd|iz  }
t        t        j                  |
            d x}x}x}	}y )N   가i  rl   Trm   ro   r1   r2   r4   r5   r6   r:   r;   rp   r   rJ   rr   rs   rt   ru   rv   )r   r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   rs   )r   	long_textr5   r[   r\   r]   r^   r_   r   r   r   s              r   ,test_embed_truncates_long_text_without_errorr   x   s/   $./I;;x$&O;PD"s"s""""s""""""4"""4""""""s"""""""yy{<(+33+,33,3333,33333333333333+333,3333333333r   c                   | j                  dg dd      }|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}}y )Nrl   Trm   ro     r2   r4   r5   r6   r:   r;   
r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r   r5   r[   r\   r]   r^   r_   s          r   test_embed_empty_list_rejectedr      s    ;;x&F;GD"s"s""""s""""""4"""4""""""s"""""""r   c                   | j                  ddgdd      }|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}}y )Nrl   z   Trm   ro   r   r2   r4   r5   r6   r:   r;   r   r   s          r    test_embed_blank_string_rejectedr      s    ;;xd&K;LD"s"s""""s""""""4"""4""""""s"""""""r   c                   | j                  ddd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}}y )Nrl   rn   Tro   r   r2   r4   r5   r6   r:   r;   r   r   s          r   'test_embed_missing_texts_field_rejectedr      s    ;;x{D&9;:D"s"s""""s""""""4"""4""""""s"""""""r   c                   | j                  ddgdd      }|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}}y )Nrl   {   Trm   ro   r   r2   r4   r5   r6   r:   r;   r   r   s          r   #test_embed_non_string_item_rejectedr      s    ;;xD&I;JD"s"s""""s""""""4"""4""""""s"""""""r   c                   | j                  ddgt        dz   z  dd      }|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}}y )Nrl   r   r   Trm   ro   r   r2   r4   r5   r6   r:   r;   )r   r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r   s          r   $test_embed_batch_over_limit_rejectedr      s    ;;x>A;M0N]a&b;cD"s"s""""s""""""4"""4""""""s"""""""r   bad_dim)  i  i  i   c                0   |j                  t        j                  dt        |             | j	                  ddgdd      }|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}	|j                         d   }|	|v }
|
slt        j                  d|
fd|	|f      t        j                  |	      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}	x}
}y)uc   768 이 아닌 결과는 조용히 자르거나 패딩하지 않고 500 으로 실패해야 한다.rD   rl   u   차원 위반 확인Trm   ro     r2   r4   r5   r6   r:   r;   N   차원 불변식 위반detail)in)z%(py1)s in %(py4)sr?   rB   rC   )setitemr   _stater   r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   rZ   )r   monkeypatchr   r5   r[   r\   r]   r^   r_   ra   rb   rc   rd   s                r   'test_embed_wrong_dimension_fails_closedr      s    w
70CD;;x1G0HW[&\;]D"s"s""""s""""""4"""4""""""s"""""""$=		H(==$(=====$(====$===(========r   c                   |j                  t        j                  dt                      | j	                  ddgdd      }|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}}y )NrD   rl   u
   NaN 확인Trm   ro   r   r2   r4   r5   r6   r:   r;   )r   r   r   r(   r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r   r   r5   r[   r\   r]   r^   r_   s           r   !test_embed_nan_values_fail_closedr      s    w	<;;xT&R;SD"s"s""""s""""""4"""4""""""s"""""""r   c                   |j                  t        j                  dt                      | j	                  dddgdd      }|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}}y )NrD   rl   abTrm   ro   r   r2   r4   r5   r6   r:   r;   )r   r   r   r.   r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r   s           r   &test_embed_count_mismatch_fails_closedr      s    w0@0BC;;xc
&N;OD"s"s""""s""""""4"""4""""""s"""""""r   c                    dgdz  g} t        j                  | d      }|d   }t        |      }d}||k(  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      t        j                  |      t        j                  |      d	z  }d
d|iz  }t        t        j                  |            d x}x}x}}y )Ng        rJ   r   )expected_countr   r2   rr   rs   rt   ru   rv   )r   validate_embeddingsrs   rR   rS   rT   rU   rV   rW   rX   rY   )rowsoutr[   r]   r   r   r_   r   s           r   *test_validate_embeddings_accepts_exact_768r      s    ECK=D

$
$T!
<C1v3v;#;#;#33v;#r   c                   |j                  t        j                  dd       | j                  ddgdd      }|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}}y)uY   모델 미로딩 시 요청 시점 로딩으로 폴백하지 않고 503 을 반환한다.rD   Nrl   u   미로딩 확인Trm   ro   i  r2   r4   r5   r6   r:   r;   )r   r   r   r   rQ   rR   rS   rT   rU   rV   rW   rX   rY   r   s           r   !test_model_not_loaded_returns_503r      s    w5;;x1C0DSW&X;YD"s"s""""s""""""4"""4""""""s"""""""r   c                     G d d      ddl }| j                  |dfd       t        j                  t        d      5  t        j                          ddd       y# 1 sw Y   yxY w)	uX   모델이 보고하는 차원이 768 이 아니면 기동 자체가 실패해야 한다.c                      e Zd Zd Zy)=test_load_model_rejects_wrong_dimension.<locals>._BadDimModelc                     y)Nr   r&   )r   s    r    get_sentence_embedding_dimensionz^test_load_model_rejects_wrong_dimension.<locals>._BadDimModel.get_sentence_embedding_dimension   s    r   N)r"   r#   r$   r   r&   r   r   _BadDimModelr      s    	r   r   r   NSentenceTransformerc                             S r   r&   )r   kr   s     r   <lambda>z9test_load_model_rejects_wrong_dimension.<locals>.<lambda>   s	    ln r   r   )match)sentence_transformerssetattrpytestraisesRuntimeErrorr   
load_model)r   r   r   s     @r   'test_load_model_rejects_wrong_dimensionr      s[      !46T 
|+D	E   s   AA(c                d   t         j                  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      d	z   d
|iz  }t        t        j                  |            dx}}t        d      D ]@  }| j                  }d}ddg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                  |      t        j                  |      t        j                  |	      t        j                  |
      t        j                  |      dz  }dd|iz  }t        t        j                  |            dx}x}x}x}	x}
x}}C t         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}}y)uP   여러 요청을 보내도 모델 로드는 startup 시 1회뿐이어야 한다.
load_countr   r2   rh   beforeri   u3   startup 후 load_count 는 1 이어야 함 (actual=)z
>assert %(py5)sr9   N   rl   r   u   로드 카운트 확인ro   r1   )z|%(py10)s
{%(py10)s = %(py8)s
{%(py8)s = %(py2)s
{%(py2)s = %(py0)s.post
}(%(py4)s, json=%(py6)s)
}.status_code
} == %(py13)sr   )r7   r8   rA   rC   rx   py10py13zassert %(py15)spy15r>   r?   rB   rC   )r   r   rR   rS   rT   rU   rV   rW   _format_assertmsgrX   rY   ranger   rQ   )r   r   rb   r[   re   r^   r   r]   r   r   @py_assert9@py_assert12@py_assert11@py_format14@py_format16ra   rc   rd   s                     r   test_model_loaded_exactly_oncer      s   ]]<(FW6Q;WWW6QWWWWWW6WWW6WWWQWWWMfXUVWWWWWWW1X e{{d8d75N4O*Pd{8*PQdQ]]dadd]addddd]adddddddvdddvddd{ddd8ddd*PdddQddd]dddaddddddddde==&+!+&!++++&!+++&+++!+++++++r   c                   t         j                  d   }| j                  dddgi       t         j                  d   }||u }|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}}y)uJ   요청 간 동일한 모델 객체(identity)가 재사용되어야 한다.rD   rl   r   u   동일 인스턴스 확인ro   rL   )z%(py1)s is %(py3)sr   rF   rH   r9   N)r   r   r   rR   rS   rW   rT   rU   rV   rX   rY   )r   r   ra   rb   re   r^   s         r   -test_model_instance_is_stable_across_requestsr      s    MM'"E
KK*F)GHKI==!*!U****!U***!******U***U*******r   c                 *   dD ]"  } t         j                  j                  | d       $ d}t        |k(  }|st	        j
                  d|fdt        |f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd	|iz  }t        t	        j                  |            dx}}d
}t        |k(  }|st	        j
                  d|fdt        |f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dz  }dd	|iz  }t        t	        j                  |            dx}}y)uW   외부 API 키 환경변수 없이도 모듈 상수가 유효하다 (외부 API 키 0).)GEMINI_API_KEYOPENAI_API_KEYANTHROPIC_API_KEYNzjhgan/ko-sroberta-multitaskr2   rh   r   ri   rH   r9   rJ   r   )osenvironpopr   rR   rS   rT   rU   rV   rW   rX   rY   r   )keyrb   r[   re   r^   s        r   !test_no_external_api_key_requiredr     s    H "


sD!"66:66666:6666666:666:66666666666=C=C==Cr   )6r%   
__future__r   builtinsrT   _pytest.assertion.rewrite	assertionrewriterR   r   sysr   fastapi.testclientr   pathinsertdirnameabspath__file__r   settingsr   r   r   r   fixturer   r   r(   r.   rf   rj   r   r   r   r   r   r   r   r   r   r   r   markparametrizer   r   r   r   r   r   r   r   r  r&   r   r   <module>r     s   	 #   	 
  ) 277??277??8#<= >  N N h  1 1? ?
' '# 	6""4#
#
#
#
# $9:> ;>###*,+ r   