diff --git a/tests/test_individuals.py b/tests/test_individuals.py index ac3f4d2..32089c1 100644 --- a/tests/test_individuals.py +++ b/tests/test_individuals.py @@ -17,7 +17,7 @@ def __init__(self, param1: int, param2: str = "default", param3: Union[int, str] self.param3 = param3 self.param4 = param4 - def evaluate(self, x_train, y_train): + def create_train_evaluate(self, x_train, y_train, x_test, y_test): return 0.9 @@ -25,12 +25,15 @@ def test_individual_init(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) assert individual.genes == genes assert individual.handler == handler assert individual.x_train == x_train assert individual.y_train == y_train + assert individual.x_test == x_test + assert individual.y_test == y_test assert individual.hyperparameters == hyperparameters assert individual.fitness is None assert individual.job_id is None @@ -40,43 +43,48 @@ def test_validate_params(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] # Should not raise any exceptions hyperparameters = {"param1": 10, "param2": "value", "param3": 3} kwargs = {"param4": 4} - individual = Individual(genes, handler, x_train, y_train, hyperparameters, **kwargs) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters, **kwargs) individual.validate_params() # Should not raise any exceptions hyperparameters = {"param1": 10, "param2": "value"} kwargs = {"param3": "3"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters, **kwargs) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters, **kwargs) individual.validate_params() # Test missing required parameter hyperparameters = {"param2": "value"} kwargs = {"param3": "3"} with pytest.raises(ValueError): - Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters, **kwargs) + individual.validate_params() # Test hyperparameter type mismatch hyperparameters = {"param1": "wrong_type", "param2": "value"} with pytest.raises(TypeError): - Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) + individual.validate_params() # Test kwarg type mismatch hyperparameters = {"param1": 10, "param2": "value"} kwargs = {"param4": "4"} with pytest.raises(TypeError): - Individual(genes, handler, x_train, y_train, hyperparameters, **kwargs) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters, **kwargs) + individual.validate_params() def test_evaluate_fitness(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) fitness = individual.evaluate_fitness() assert fitness == 0.9 assert individual.fitness == 0.9 @@ -86,8 +94,9 @@ def test_get_fitness(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) assert individual.get_fitness() is None individual.evaluate_fitness() assert individual.get_fitness() == 0.9 @@ -97,8 +106,9 @@ def test_send_to_queue(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) server = MagicMock(spec=RedisController) server.send_job.return_value = "job_id" individual.send_to_queue(server) @@ -110,8 +120,9 @@ def test_read_from_queue(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) server = MagicMock(spec=RedisController) server.wait_for_result.return_value = 0.9 individual.job_id = "job_id" @@ -124,8 +135,9 @@ def test_getitem_setitem(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) assert individual["param1"] == 10 individual["param1"] = 20 assert individual["param1"] == 20 @@ -136,10 +148,11 @@ def test_reproduce(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters1 = {"param1": 10, "param2": "value1"} hyperparameters2 = {"param1": 20, "param2": "value2"} - individual1 = Individual(genes, handler, x_train, y_train, hyperparameters1) - individual2 = Individual(genes, handler, x_train, y_train, hyperparameters2) + individual1 = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters1) + individual2 = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters2) child = individual1.reproduce(individual2, rate=0.5) assert isinstance(child, Individual) assert child.handler == handler @@ -152,10 +165,11 @@ def test_crossover(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters1 = {"param1": 10, "param2": "value1"} hyperparameters2 = {"param1": 20, "param2": "value2"} - individual1 = Individual(genes, handler, x_train, y_train, hyperparameters1) - individual2 = Individual(genes, handler, x_train, y_train, hyperparameters2) + individual1 = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters1) + individual2 = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters2) individual1.crossover(individual2, rate=1.0) assert individual1["param1"] == 20 assert individual1["param2"] == "value2" @@ -169,8 +183,9 @@ def test_mutate(): genes = [gene1, gene2] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 1, "param2": "4"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) individual.mutate(rate=1.0) assert individual["param1"] in [1, 2, 3] assert individual["param2"] in ["4", "5", "6"] @@ -180,8 +195,9 @@ def test_duplicate(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) duplicate = individual.duplicate() assert isinstance(duplicate, Individual) assert duplicate.genes == genes @@ -196,6 +212,7 @@ def test_str(): genes = [Gene("gene1"), Gene("gene2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] + x_test, y_test = [6, 5, 4], [3, 2, 1] hyperparameters = {"param1": 10, "param2": "value"} - individual = Individual(genes, handler, x_train, y_train, hyperparameters) + individual = Individual(genes, handler, x_train, y_train, x_test, y_test, hyperparameters) assert str(individual) == pprint.pformat(hyperparameters) diff --git a/tests/test_models.py b/tests/test_models.py new file mode 100644 index 0000000..c030dbe --- /dev/null +++ b/tests/test_models.py @@ -0,0 +1,58 @@ +import numpy as np +import pytest + +from src.gentun.models.base import Handler, KFoldCrossValidation + + +class MockModel(Handler): + def create_train_evaluate(self, x_train, y_train, x_test, y_test): + return np.mean(y_test) # Dummy evaluation metric + + +@pytest.fixture +def data(): + x_train = np.random.rand(100, 10) + y_train = np.random.randint(0, 2, size=(100,)) + return x_train, y_train + + +def test_initialization(): + params = {"param1": 1, "param2": 2} + handler = Handler(**params) + assert handler.model_params == params + + +def test_evaluate_not_implemented(): + handler = Handler() + with pytest.raises(NotImplementedError): + handler(None, None, None, None) + + +def test_kfold_cross_validation(data): + x_train, y_train = data + model = KFoldCrossValidation(folds=5, stratified=True, shuffle=True) + model.create_train_evaluate = MockModel().create_train_evaluate + metric = model(x_train, y_train) + assert isinstance(metric, float) + assert metric >= 0 + + +def test_kfold_cross_validation_with_one_hot_labels(data): + x_train, y_train = data + y_train_one_hot = np.eye(2)[y_train] # Convert to one-hot encoding + model = KFoldCrossValidation(folds=5, stratified=True, shuffle=True) + model.create_train_evaluate = MockModel().create_train_evaluate + metric = model(x_train, y_train_one_hot) + assert isinstance(metric, float) + assert metric >= 0 + + +def test_kfold_cross_validation_ignores_test_data(data): + x_train, y_train = data + x_test = np.random.rand(20, 10) + y_test = np.random.randint(0, 2, size=(20,)) + model = KFoldCrossValidation(folds=5, stratified=True, shuffle=True) + model.create_train_evaluate = MockModel().create_train_evaluate + metric = model(x_train, y_train, x_test, y_test) + assert isinstance(metric, float) + assert metric >= 0 diff --git a/tests/test_populations.py b/tests/test_populations.py index f8780a8..b428047 100644 --- a/tests/test_populations.py +++ b/tests/test_populations.py @@ -14,7 +14,7 @@ def __init__(self, param1: int, param2: str = "default"): self.param1 = param1 self.param2 = param2 - def evaluate(self, x_train, y_train): + def create_train_evaluate(self, x_train, y_train, x_test, y_test): return 0.9 @@ -83,7 +83,10 @@ def test_population_init_with_individuals(): genes = [MockIntGene("param1"), MockStrGene("param2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] - individuals = [Individual(genes, handler, x_train, y_train, {"param1": 1, "param2": "2"}) for _ in range(5)] + x_test, y_test = [6, 5, 4], [3, 2, 1] + individuals = [ + Individual(genes, handler, x_train, y_train, x_test, y_test, {"param1": 1, "param2": "2"}) for _ in range(5) + ] population = Population(genes, handler, individuals, x_train, y_train) assert len(population) == 5 assert all(isinstance(individual, Individual) for individual in population) @@ -131,7 +134,10 @@ def test_population_get_fittest(): genes = [MockIntGene("param1"), MockStrGene("param2")] handler = MockHandler x_train, y_train = [1, 2, 3], [4, 5, 6] - individuals = [Individual(genes, handler, x_train, y_train, {"param1": 1, "param2": "2"}) for _ in range(5)] + x_test, y_test = [6, 5, 4], [3, 2, 1] + individuals = [ + Individual(genes, handler, x_train, y_train, x_test, y_test, {"param1": 1, "param2": "2"}) for _ in range(5) + ] population = Population(genes, handler, individuals, x_train, y_train) fittest = population.get_fittest() assert isinstance(fittest, Individual) @@ -145,8 +151,11 @@ def test_population_get_fittest_with_redis(mock_send_to_queue, mock_read_from_qu handler = MockHandler controller = RedisController("test") x_train, y_train = [1, 2, 3], [4, 5, 6] - individuals = [Individual(genes, handler, x_train, y_train, {"param1": 1, "param2": "2"}) for _ in range(5)] - population = Population(genes, handler, individuals, x_train, y_train, controller=controller) + x_test, y_test = [6, 5, 4], [3, 2, 1] + individuals = [ + Individual(genes, handler, x_train, y_train, x_test, y_test, {"param1": 1, "param2": "2"}) for _ in range(5) + ] + population = Population(genes, handler, individuals, x_train, y_train, x_test, y_test, controller=controller) fittest = population.get_fittest() assert isinstance(fittest, Individual) assert mock_send_to_queue.call_count == 5