@@ -324,3 +324,111 @@ pub fn appraise_investment(
324324 } ;
325325 appraisal_method ( model, asset, max_capacity, commodity, coefficients, demand)
326326}
327+
328+ #[ cfg( test) ]
329+ mod tests {
330+ use super :: * ;
331+ use crate :: finance:: ProfitabilityIndex ;
332+ use crate :: units:: { Money , MoneyPerActivity } ;
333+
334+ #[ test]
335+ fn lcox_compare_equal ( ) {
336+ let metric1 = LCOXMetric :: new ( MoneyPerActivity ( 10.0 ) ) ;
337+ let metric2 = LCOXMetric :: new ( MoneyPerActivity ( 10.0 ) ) ;
338+
339+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Equal ) ;
340+ }
341+
342+ #[ test]
343+ fn lcox_compare_less_is_better ( ) {
344+ let metric1 = LCOXMetric :: new ( MoneyPerActivity ( 5.0 ) ) ;
345+ let metric2 = LCOXMetric :: new ( MoneyPerActivity ( 10.0 ) ) ;
346+
347+ // metric1 has lower cost, so it's better (Less)
348+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Less ) ;
349+ }
350+
351+ #[ test]
352+ fn lcox_compare_greater_is_worse ( ) {
353+ let metric1 = LCOXMetric :: new ( MoneyPerActivity ( 15.0 ) ) ;
354+ let metric2 = LCOXMetric :: new ( MoneyPerActivity ( 10.0 ) ) ;
355+
356+ // metric1 has higher cost, so it's worse (Greater)
357+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Greater ) ;
358+ }
359+
360+ #[ test]
361+ fn npv_compare_both_zero_fixed_cost ( ) {
362+ let metric1 = NPVMetric :: new ( ProfitabilityIndex {
363+ total_annualised_surplus : Money ( 100.0 ) ,
364+ annualised_fixed_cost : Money ( 0.0 ) ,
365+ } ) ;
366+ let metric2 = NPVMetric :: new ( ProfitabilityIndex {
367+ total_annualised_surplus : Money ( 50.0 ) ,
368+ annualised_fixed_cost : Money ( 0.0 ) ,
369+ } ) ;
370+
371+ // Compare by surplus: metric1 (100) is better than metric2 (50)
372+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Less ) ;
373+ }
374+
375+ #[ test]
376+ fn npv_compare_both_zero_fixed_cost_equal ( ) {
377+ let metric1 = NPVMetric :: new ( ProfitabilityIndex {
378+ total_annualised_surplus : Money ( 100.0 ) ,
379+ annualised_fixed_cost : Money ( 0.0 ) ,
380+ } ) ;
381+ let metric2 = NPVMetric :: new ( ProfitabilityIndex {
382+ total_annualised_surplus : Money ( 100.0 ) ,
383+ annualised_fixed_cost : Money ( 0.0 ) ,
384+ } ) ;
385+
386+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Equal ) ;
387+ }
388+
389+ #[ test]
390+ fn npv_compare_zero_vs_nonzero_fixed_cost ( ) {
391+ let metric_zero = NPVMetric :: new ( ProfitabilityIndex {
392+ total_annualised_surplus : Money ( 10.0 ) ,
393+ annualised_fixed_cost : Money ( 0.0 ) ,
394+ } ) ;
395+ let metric_nonzero = NPVMetric :: new ( ProfitabilityIndex {
396+ total_annualised_surplus : Money ( 1000.0 ) ,
397+ annualised_fixed_cost : Money ( 100.0 ) ,
398+ } ) ;
399+
400+ // Zero fixed cost is always better
401+ assert_eq ! ( metric_zero. compare( & metric_nonzero) , Ordering :: Less ) ;
402+ assert_eq ! ( metric_nonzero. compare( & metric_zero) , Ordering :: Greater ) ;
403+ }
404+
405+ #[ test]
406+ fn npv_compare_both_nonzero_fixed_cost ( ) {
407+ let metric1 = NPVMetric :: new ( ProfitabilityIndex {
408+ total_annualised_surplus : Money ( 200.0 ) ,
409+ annualised_fixed_cost : Money ( 100.0 ) ,
410+ } ) ;
411+ let metric2 = NPVMetric :: new ( ProfitabilityIndex {
412+ total_annualised_surplus : Money ( 150.0 ) ,
413+ annualised_fixed_cost : Money ( 100.0 ) ,
414+ } ) ;
415+
416+ // Compare by profitability index: 200/100 = 2.0 vs 150/100 = 1.5
417+ // metric1 is better (higher PI)
418+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Less ) ;
419+ }
420+
421+ #[ test]
422+ fn npv_compare_both_nonzero_fixed_cost_equal ( ) {
423+ let metric1 = NPVMetric :: new ( ProfitabilityIndex {
424+ total_annualised_surplus : Money ( 200.0 ) ,
425+ annualised_fixed_cost : Money ( 100.0 ) ,
426+ } ) ;
427+ let metric2 = NPVMetric :: new ( ProfitabilityIndex {
428+ total_annualised_surplus : Money ( 200.0 ) ,
429+ annualised_fixed_cost : Money ( 100.0 ) ,
430+ } ) ;
431+
432+ assert_eq ! ( metric1. compare( & metric2) , Ordering :: Equal ) ;
433+ }
434+ }
0 commit comments