code: def test_config_trainer_bad_optimizer():
      config = {
          "input_features": [
              category_feature(
                  encoder={"type": "dense", "vocab_size": 2},
                  reduce_input="sum",
              ),
              number_feature(),
          ],
          "output_features": [binary_feature()],
          "combiner": {
              "type": "tabnet",
          },
          TRAINER: {},
      }
      check_schema(config)
  
      # Test manually set-to-null optimizer vs unspecified:
      config[TRAINER]["optimizer"] = None
      with pytest.raises(ConfigValidationError):
          check_schema(config)
      assert ECDTrainerConfig.Schema().load({}).optimizer is not None
  
      # Test all types in optimizer_registry supported:
      for key in optimizer_registry.keys():
          config[TRAINER]["optimizer"] = {"type": key}
          check_schema(config)
  
      # Test invalid optimizer type:
      config[TRAINER]["optimizer"] = {"type": 0}
      with pytest.raises(ConfigValidationError):
          check_schema(config)
      config[TRAINER]["optimizer"] = {"type": "invalid"}
      with pytest.raises(ConfigValidationError):
          check_schema(config)
  
file_path: ludwig/tests/ludwig/config_validation/test_validate_config_trainer.py
imports: import pytest
  from ludwig.config_validation.validation import check_schema
  from ludwig.constants import TRAINER
  from ludwig.error import ConfigValidationError
  from ludwig.schema.optimizers import optimizer_registry
  from ludwig.schema.trainer import ECDTrainerConfig
  from tests.integration_tests.utils import binary_feature, category_feature, number_feature
label_desc: Use image node_id 2 for calling a global function with example usage: test_config_trainer_bad_optimizer() without return types