
    xr5i                         d Z ddlZddlmc mZ ddlZddlm	Z	m
Z
mZ ddlmZ ddlmZmZmZ  G d d      Z G d d	      Zy)
zTests for KPI calculator.    N)KPINodeConfigNodeTypeKPICategory)KPITree)KPICalculatorFormulaParserFormulaErrorc                       e Zd ZdZej
                  d        Zd Zd Zd Z	ej                  j                  dddd	d
dfddd	d
d	fddd	d
dfddd	d
dfddd	dddfddd	dddfg      d        Zd Zd Zd Zd Zd Zy)TestFormulaParserzTests for FormulaParser.c                     t               S )N)r   selfs    j/var/www/tkim.planitai.co.jp/gemegg/20251207-make-pdf-report/project/planitai-kpi/tests/test_calculator.pyparserzTestFormulaParser.parser   s
        c                 z   d}|j                  |      }g d}||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	)
zTest variable extraction.z{a} + {b} * {c}abc==z%(py0)s == %(py3)s	variablespy0py3assert %(py5)spy5N)	parse_variables
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)r   r   formular   @py_assert2@py_assert1@py_format4@py_format6s           r   test_parse_variablesz&TestFormulaParser.test_parse_variables   sp    #**73	++yO++++yO++++++y+++y+++O+++++++r   c                    d}d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                  |      d	z  }d
d|iz  }t        t        j                  |            dx}}y)zTest variable substitution.	{a} + {b}
      r   r   z10 + 20r   r   resultr   r   r   N)	substitute_variablesr!   r"   r#   r$   r%   r&   r'   r(   )	r   r   r)   valuesr4   r*   r+   r,   r-   s	            r   test_substitute_variablesz+TestFormulaParser.test_substitute_variables   s|    #,,Wf=""v""""v""""""v"""v""""""""""r   c                     d}ddi}t        j                  t        d      5  |j                  ||       ddd       y# 1 sw Y   yxY w)z(Test that missing variables raise error.r0   r   r1   zMissing variable)matchN)pytestraisesr	   r5   )r   r   r)   r6   s       r   test_missing_variable_raisesz.TestFormulaParser.test_missing_variable_raises   sD    r]]</AB 	9''8	9 	9 	9s	   >Azformula,values,expectedr0   r1      r3      z	{a} - {b}z	{a} * {b}2   	{a} / {b}   z({a} + {b}) * {c}r      z{a} * {b} + {c}   5   c                    |j                  ||      }||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)	z!Test basic arithmetic operations.r   )z%(py0)s == %(py2)sr4   expected)r   py2zassert %(py4)spy4N	evaluater!   r"   r#   r$   r%   r&   r'   r(   )	r   r   r)   r6   rF   r4   r+   @py_format3@py_format5s	            r   test_evaluate_basic_operationsz0TestFormulaParser.test_evaluate_basic_operations%   s|     &1!!!!v!!!!!!v!!!v!!!!!!!!!!!!!!!!r   c                 z   |j                  d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  }d
d|iz  }t        t        j                  |            dx}}y)z Test division by zero returns 0.r@   r1   r   r3   g        r   r   r4   r   r   r   NrI   )r   r   r4   r*   r+   r,   r-   s          r   test_evaluate_division_by_zeroz0TestFormulaParser.test_evaluate_division_by_zero5   so    BQ.?@v}vvvr   c                    |j                  dddd      }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)zTest decimal calculations.r@   r1   rC   r3   gDl
@g{Gz?<)z;%(py6)s
{%(py6)s = %(py0)s((%(py1)s - %(py3)s))
} < %(py9)sabsr4   )r   py1r   py6py9zassert %(py11)spy11N)
rJ   rS   r!   r"   r#   r$   r%   r&   r'   r(   )
r   r   r4   r*   @py_assert4@py_assert5@py_assert8@py_assert7@py_format10@py_format12s
             r   test_evaluate_decimalz'TestFormulaParser.test_evaluate_decimal:   s    BQ.?@!)6E>)s>")T)"T))))"T))))))s)))s))))))6)))6)))E)))")))T))))))))r   c                    |j                  dddi      }d}| }||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}x}}y
)zTest negative numbers.z-{a}r   r1   r   )z%(py0)s == -%(py3)sr4   r   assert %(py6)srU   NrI   )r   r   r4   r*   rX   r+   rL   @py_format7s           r   test_evaluate_negativez(TestFormulaParser.test_evaluate_negative?   su    #r3"v}vvv"r   c                     t        j                  t              5  |j                  dddd       ddd       y# 1 sw Y   yxY w)z*Test that invalid expressions raise error.z
{a} @@ {b}r1   r=   r3   Nr:   r;   r	   rJ   )r   r   s     r   test_invalid_expression_raisesz0TestFormulaParser.test_invalid_expression_raisesD   s6    ]]<( 	=OOL*;<	= 	= 	=s	   9Ac                     g d}|D ]6  }t        j                  t              5  |j                  |i        ddd       8 y# 1 sw Y   CxY w)z$Test that dangerous code is blocked.)z__import__('os')zeval('1+1')zexec('print(1)')Nrd   )r   r   dangerous_expressionsexprs       r   test_dangerous_code_blockedz-TestFormulaParser.test_dangerous_code_blockedI   sO    !

 * 	*D|, *b)* *	** *s   AA
	N)__name__
__module____qualname____doc__r:   fixturer   r.   r7   r<   markparametrizerM   rO   r^   rb   re   ri    r   r   r   r   
   s    "^^ ,#9 [[!+R0+Q/+R0+Q/ ";R@bqq 92>	

"
"

*

=
	*r   r   c                   p    e Zd ZdZej
                  d        Zej
                  d        Zd Zd Z	d Z
d Zy)	TestKPICalculatorzTests for KPICalculator.c                     t        ddt        j                  dddg      t        ddt        j                        t        dd	t        j                        gS )
z-Simple tree: revenue = contracts * avg_price.revenueRevenue{contracts} * {avg_price}	contracts	avg_priceidnametyper)   children	Contractsr{   r|   r}   	Avg Price)r   r   KGIINPUTr   s    r   simple_tree_configz$TestKPICalculator.simple_tree_configX   s\     \\3%{3  ^^
  ^^
 	
r   c                    t        ddt        j                  dddg      t        ddt        j                  dd	d
g      t        ddt        j                        t        d	dt        j                  dddg      t        d
dt        j                        t        ddt        j                        t        ddt        j                        gS )z"Complex tree with multiple levels.ru   rv   rw   rx   ry   rz   r   z{meetings} * {close_rate}meetings
close_rater   r   Meetingsz{leads} * {meeting_rate}leadsmeeting_ratez
Close RateLeadszMeeting Rate)r   r   r   KPIr   r   s    r   complex_tree_configz%TestKPICalculator.complex_tree_configo   s     \\3%{3  \\3$l3  ^^
 \\2!>2 !^^
 ^^
 !#^^K*
 *	
r   c                    t        j                  |      }|j                  ddd       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}}|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)zTest simple tree calculation.d   i  )rx   ry   ru     r   z%(py1)s == %(py4)srT   rH   r`   rU   Nrx   ry   
r   from_config
set_valuesr   	calculater!   r"   r&   r'   r(   )
r   r   tree
calculatorresults@py_assert0@py_assert3r*   rL   ra   s
             r   test_simple_calculationz)TestKPICalculator.test_simple_calculation   s2   ""#56c=>"4(
&&(y!+V+!V++++!V+++!+++V+++++++{#*s*#s****#s***#***s*******{#+t+#t++++#t+++#+++t+++++++r   c                    t        j                  |      }|j                  ddddd       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}}|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)zTest complex tree calculation.  333333?皙?r   r   r   r   ry   r   i,  r   r   r   r`   rU   Nrx   <   ru   ir   )
r   r   r   r   r   r   r   r*   rL   ra   s
             r   test_complex_calculationz*TestKPICalculator.test_complex_calculation   sF   ""#67 #!#		
 #4(
&&( z")c)"c))))"c)))")))c))))))) {#)r)#r))))#r)))#)))r))))))) y!-X-!X----!X---!---X-------r   c                 d   t        j                  |      }t        |      }|j                         }|j                  }d} ||      }|j                  }d}	 ||	      }
||
k  }|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                  |      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}x}x}	}
|j                  }d
} ||      }|j                  }d}	 ||	      }
||
k  }|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                  |      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}x}x}	}
|j                  }d} ||      }|j                  }d}	 ||	      }
||
k  }|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                  |      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}x}x}	}
|j                  }d} ||      }|j                  }d}	 ||	      }
||
k  }|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                  |      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}x}x}	}
y	)z0Test that nodes are calculated in correct order.r   r   rQ   )z%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.index
}(%(py4)s)
} < %(py14)s
{%(py14)s = %(py10)s
{%(py10)s = %(py8)s.index
}(%(py12)s)
}order)r   rG   rH   rU   py8py10py12py14zassert %(py16)spy16Nr   rx   ru   )r   r   r   _get_calculation_orderindexr!   r"   r#   r$   r%   r&   r'   r(   )r   r   r   r   r   r+   r   rY   @py_assert9@py_assert11@py_assert13r[   @py_format15@py_format17s                 r   test_calculation_orderz(TestKPICalculator.test_calculation_order   s   ""#67"4(
113 {{=7={7#=ekk=*=k*&==#&=====#&=======u===u==={===7===#======e===e===k===*===&========={{D>D{>*DU[[DD[-DD*-DDDDD*-DDDDDDDuDDDuDDD{DDD>DDD*DDDDDDUDDDUDDD[DDDDDD-DDDDDDDDD{{A:A{:&AA[A[)AA&)AAAAA&)AAAAAAAuAAAuAAA{AAA:AAA&AAAAAAAAAAAAAAA[AAA)AAAAAAAAA{{@;@{;'@%++@i@+i*@@'*@@@@@'*@@@@@@@u@@@u@@@{@@@;@@@'@@@@@@%@@@%@@@+@@@i@@@*@@@@@@@@@r   c                    t        j                  |      }|j                  ddddd       t        |      }|j	                         }|j                  ddi      }|j                  d   }|j                  }d}||k(  }	|	st        j                  d|	fd	||f      t        j                  |      t        j                  |      t        j                  |      d
z  }
dd|
iz  }t        t        j                  |            dx}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)z/Test simulation doesn't modify original values.r   r   r   r   r   r   g      ?r   )z-%(py3)s
{%(py3)s = %(py1)s.value
} == %(py6)s)rT   r   rU   zassert %(py8)sr   Nrx   K   r   r   r`   rU   ru   i`4<)r   r   r   r   r   simulatenodesvaluer!   r"   r&   r'   r(   )r   r   r   r   original	simulatedr   r*   rY   rX   ra   @py_format9r   rL   s                 r   test_simulatezTestKPICalculator.test_simulate   sy   ""#67 #!#		
 #4(
 '') ''t(<=	 zz,'4'--44-4444-444'444-4444444444
 %++%++++%+++%++++++++++#/x/#x////#x///#///x///////r   N)rj   rk   rl   rm   r:   rn   r   r   r   r   r   r   rq   r   r   rs   rs   U   sI    "^^
 
, ^^,
 ,
\
,.0A0r   rs   )rm   builtinsr#   _pytest.assertion.rewrite	assertionrewriter!   r:   
src.configr   r   r   src.kpi.treer   src.kpi.calculatorr   r   r	   r   rs   rq   r   r   <module>r      s7        ; ;   I IH* H*VU0 U0r   