Skip to content

Commit 127c9aa

Browse files
authored
Merge pull request #5 from alexnodeland/claude/complete-test-coverage-01TZwe6xCXkG1f4TZuQQKydP
2 parents 2bf6e64 + dac3006 commit 127c9aa

5 files changed

Lines changed: 671 additions & 3 deletions

File tree

crates/fugue-evo-wasm/tests/wasm_tests.rs

Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,3 +572,311 @@ fn test_fitness_info() {
572572
let err = get_fitness_info("unknown_function");
573573
assert!(err.is_err());
574574
}
575+
576+
// ============================================================================
577+
// Evolution Strategy Extended Tests
578+
// ============================================================================
579+
580+
use fugue_evo_wasm::ESSelection;
581+
582+
#[wasm_bindgen_test]
583+
fn test_evolution_strategy_mu_plus_lambda() {
584+
let mut optimizer = EvolutionStrategyOptimizer::new(3);
585+
optimizer.set_mu(5);
586+
optimizer.set_lambda(20);
587+
optimizer.set_selection_strategy(ESSelection::MuPlusLambda);
588+
optimizer.set_initial_sigma(0.5);
589+
optimizer.set_self_adaptive(true);
590+
optimizer.set_population_size(20);
591+
optimizer.set_max_generations(30);
592+
optimizer.set_bounds(-5.0, 5.0);
593+
optimizer.set_seed(42);
594+
// Can't actually call optimize without a JS fitness function
595+
// Just verify configuration doesn't panic
596+
}
597+
598+
#[wasm_bindgen_test]
599+
fn test_evolution_strategy_mu_comma_lambda() {
600+
let mut optimizer = EvolutionStrategyOptimizer::new(3);
601+
optimizer.set_mu(5);
602+
optimizer.set_lambda(30);
603+
optimizer.set_selection_strategy(ESSelection::MuCommaLambda);
604+
optimizer.set_initial_sigma(1.0);
605+
optimizer.set_self_adaptive(false);
606+
optimizer.set_population_size(30);
607+
optimizer.set_max_generations(20);
608+
optimizer.set_bounds(-10.0, 10.0);
609+
optimizer.set_seed(123);
610+
// Configuration verified by not panicking
611+
}
612+
613+
// ============================================================================
614+
// BitStringResult Extended Tests
615+
// ============================================================================
616+
617+
#[wasm_bindgen_test]
618+
fn test_bitstring_result_methods() {
619+
let mut optimizer = BitStringOptimizer::new(16);
620+
optimizer.set_population_size(30);
621+
optimizer.set_max_generations(50);
622+
optimizer.set_seed(42);
623+
624+
let result = optimizer.solve_one_max().expect("Should succeed");
625+
626+
// Test count_ones
627+
let ones_count = result.count_ones();
628+
assert!(ones_count <= 16);
629+
assert!(ones_count > 0);
630+
631+
// Test best_genome_string
632+
let genome_str = result.best_genome_string();
633+
assert_eq!(genome_str.len(), 16);
634+
assert!(genome_str.chars().all(|c| c == '0' || c == '1'));
635+
636+
// Test fitness_history
637+
let history = result.fitness_history();
638+
assert!(!history.is_empty());
639+
}
640+
641+
// ============================================================================
642+
// MultiObjectiveResult Extended Tests
643+
// ============================================================================
644+
645+
#[wasm_bindgen_test]
646+
fn test_multi_objective_result_methods() {
647+
let mut optimizer = Nsga2Optimizer::new(5, 2);
648+
optimizer.set_population_size(30);
649+
optimizer.set_max_generations(20);
650+
optimizer.set_seed(42);
651+
652+
let result = optimizer
653+
.optimize_zdt(ZdtProblem::Zdt1)
654+
.expect("Should succeed");
655+
656+
// Test front_size
657+
let front_size = result.front_size();
658+
assert!(front_size > 0);
659+
660+
// Test generations and evaluations
661+
assert_eq!(result.generations(), 20);
662+
assert!(result.evaluations() > 0);
663+
664+
// Test get_solution
665+
if front_size > 0 {
666+
let solution = result.get_solution(0).expect("Should get first solution");
667+
assert!(!solution.genome().is_empty());
668+
assert!(!solution.objectives().is_empty());
669+
}
670+
671+
// Test all_genomes and all_objectives
672+
let all_genomes = result.all_genomes();
673+
let all_objectives = result.all_objectives();
674+
assert!(!all_genomes.is_empty());
675+
assert!(!all_objectives.is_empty());
676+
677+
// Test to_json
678+
let json = result.to_json().expect("Should serialize to JSON");
679+
assert!(json.contains("pareto_front"));
680+
}
681+
682+
// ============================================================================
683+
// Additional Fitness Function Tests
684+
// ============================================================================
685+
686+
#[wasm_bindgen_test]
687+
fn test_dixon_price_optimization() {
688+
let mut optimizer = RealVectorOptimizer::new(3);
689+
optimizer.set_population_size(30);
690+
optimizer.set_max_generations(50);
691+
optimizer.set_bounds(-10.0, 10.0);
692+
optimizer.set_fitness("dixon_price");
693+
optimizer.set_seed(42);
694+
695+
let result = optimizer
696+
.optimize()
697+
.expect("Dixon-Price optimization should succeed");
698+
assert!(result.best_fitness() >= 0.0);
699+
}
700+
701+
#[wasm_bindgen_test]
702+
fn test_styblinski_tang_optimization() {
703+
let mut optimizer = RealVectorOptimizer::new(3);
704+
optimizer.set_population_size(30);
705+
optimizer.set_max_generations(50);
706+
optimizer.set_bounds(-5.0, 5.0);
707+
optimizer.set_fitness("styblinski_tang");
708+
optimizer.set_seed(42);
709+
710+
let result = optimizer
711+
.optimize()
712+
.expect("Styblinski-Tang optimization should succeed");
713+
// Result can be negative for Styblinski-Tang
714+
assert!(result.evaluations() > 0);
715+
}
716+
717+
// ============================================================================
718+
// Interactive Evolution Tests
719+
// ============================================================================
720+
721+
use fugue_evo_wasm::{InteractiveOptimizer, StepResultType, WasmEvaluationMode};
722+
723+
#[wasm_bindgen_test]
724+
fn test_interactive_optimizer_creation() {
725+
let _optimizer = InteractiveOptimizer::new(5);
726+
}
727+
728+
#[wasm_bindgen_test]
729+
fn test_interactive_optimizer_with_config() {
730+
let _optimizer = InteractiveOptimizer::with_config(
731+
5, // dimension
732+
20, // population_size
733+
WasmEvaluationMode::Rating, // evaluation_mode
734+
5, // batch_size
735+
10, // max_generations
736+
);
737+
}
738+
739+
#[wasm_bindgen_test]
740+
fn test_interactive_optimizer_with_extended_config() {
741+
let _optimizer = InteractiveOptimizer::with_extended_config(
742+
5, // dimension
743+
20, // population_size
744+
WasmEvaluationMode::Pairwise, // evaluation_mode
745+
5, // batch_size
746+
3, // select_count
747+
10, // max_generations
748+
2, // elitism_count
749+
0.8, // min_coverage
750+
0.9, // crossover_probability
751+
0.1, // mutation_probability
752+
-5.0, // lower_bound
753+
5.0, // upper_bound
754+
);
755+
}
756+
757+
#[wasm_bindgen_test]
758+
fn test_interactive_optimizer_step() {
759+
let mut optimizer = InteractiveOptimizer::with_config(3, 10, WasmEvaluationMode::Rating, 3, 5);
760+
optimizer.set_seed(42);
761+
762+
// First step should request evaluation
763+
let step_result = optimizer.step();
764+
assert!(step_result.needs_evaluation());
765+
assert!(matches!(
766+
step_result.result_type(),
767+
StepResultType::NeedsEvaluation
768+
));
769+
770+
// Verify we can get the request
771+
let request = step_result.get_request().expect("Should have request");
772+
assert!(request.candidate_count() > 0);
773+
}
774+
775+
#[wasm_bindgen_test]
776+
fn test_interactive_optimizer_getters() {
777+
let mut optimizer = InteractiveOptimizer::with_config(3, 10, WasmEvaluationMode::Rating, 3, 5);
778+
optimizer.set_seed(42);
779+
780+
// Test initial state getters
781+
assert_eq!(optimizer.generation(), 0);
782+
assert_eq!(optimizer.population_size(), 10);
783+
assert!(optimizer.get_coverage() >= 0.0);
784+
785+
// Get population JSON
786+
let pop_json = optimizer
787+
.get_population_json()
788+
.expect("Should get population JSON");
789+
assert!(pop_json.contains('['));
790+
}
791+
792+
#[wasm_bindgen_test]
793+
fn test_interactive_optimizer_batch_selection_mode() {
794+
let optimizer =
795+
InteractiveOptimizer::with_config(3, 10, WasmEvaluationMode::BatchSelection, 5, 5);
796+
797+
assert_eq!(optimizer.population_size(), 10);
798+
}
799+
800+
// ============================================================================
801+
// Evaluation Request Tests
802+
// ============================================================================
803+
804+
#[wasm_bindgen_test]
805+
fn test_evaluation_request_methods() {
806+
let mut optimizer = InteractiveOptimizer::with_config(3, 10, WasmEvaluationMode::Rating, 3, 5);
807+
optimizer.set_seed(42);
808+
809+
let step_result = optimizer.step();
810+
let request = step_result.get_request().expect("Should have request");
811+
812+
// Test request type
813+
use fugue_evo_wasm::RequestType;
814+
assert!(matches!(request.request_type(), RequestType::Rating));
815+
816+
// Test candidate access
817+
let candidate_count = request.candidate_count();
818+
assert!(candidate_count > 0);
819+
820+
// Test get candidate
821+
if candidate_count > 0 {
822+
let candidate = request
823+
.get_candidate(0)
824+
.expect("Should get first candidate");
825+
assert!(candidate.genome().len() == 3);
826+
assert!(!candidate.is_evaluated());
827+
assert_eq!(candidate.evaluation_count(), 0);
828+
}
829+
830+
// Test get candidate IDs
831+
let ids = request.get_candidate_ids();
832+
assert_eq!(ids.len(), candidate_count);
833+
834+
// Test get candidates JSON
835+
let json = request
836+
.get_candidates_json()
837+
.expect("Should serialize candidates");
838+
assert!(json.contains('['));
839+
840+
// Test scale bounds
841+
assert!(request.scale_min() <= request.scale_max());
842+
843+
// Test to_json
844+
let request_json = request.to_json().expect("Should serialize request");
845+
assert!(request_json.contains("request_type"));
846+
}
847+
848+
// ============================================================================
849+
// WasmCandidate Tests
850+
// ============================================================================
851+
852+
#[wasm_bindgen_test]
853+
fn test_wasm_candidate_methods() {
854+
let mut optimizer = InteractiveOptimizer::with_config(3, 10, WasmEvaluationMode::Rating, 3, 5);
855+
optimizer.set_seed(42);
856+
857+
let step_result = optimizer.step();
858+
let request = step_result.get_request().expect("Should have request");
859+
let candidate = request.get_candidate(0).expect("Should get candidate");
860+
861+
// Test id
862+
let id = candidate.id();
863+
assert!(id < 1000); // Reasonable ID
864+
865+
// Test genome
866+
let genome = candidate.genome();
867+
assert_eq!(genome.len(), 3);
868+
869+
// Test fitness (should be None initially)
870+
assert!(candidate.fitness().is_none());
871+
872+
// Test evaluation count
873+
assert_eq!(candidate.evaluation_count(), 0);
874+
875+
// Test is_evaluated
876+
assert!(!candidate.is_evaluated());
877+
878+
// Test to_json
879+
let json = candidate.to_json().expect("Should serialize candidate");
880+
assert!(json.contains("id"));
881+
assert!(json.contains("genome"));
882+
}

0 commit comments

Comments
 (0)