diff --git a/esphome/__main__.py b/esphome/__main__.py index 9dcc5cdfe8..be4551f6b5 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -1003,8 +1003,8 @@ def parse_args(argv): default=[], ) options_parser.add_argument( - "--ignore-pin-conflicts", - help="Disable pin conflict validation (for testing grouped components)", + "--testing-mode", + help="Enable testing mode (disables validation checks for grouped component testing)", action="store_true", default=False, ) @@ -1266,7 +1266,7 @@ def run_esphome(argv): args = parse_args(argv) CORE.dashboard = args.dashboard - CORE.ignore_pin_conflicts = args.ignore_pin_conflicts + CORE.testing_mode = args.testing_mode # Create address cache from command-line arguments CORE.address_cache = AddressCache.from_cli_args( diff --git a/esphome/core/__init__.py b/esphome/core/__init__.py index 744e32abf8..43febd28a2 100644 --- a/esphome/core/__init__.py +++ b/esphome/core/__init__.py @@ -529,8 +529,8 @@ class EsphomeCore: self.dashboard = False # True if command is run from vscode api self.vscode = False - # True if pin conflict validation should be ignored - self.ignore_pin_conflicts = False + # True if running in testing mode (disables validation checks for grouped testing) + self.testing_mode = False # The name of the node self.name: str | None = None # The friendly name of the node diff --git a/esphome/core/entity_helpers.py b/esphome/core/entity_helpers.py index e1b2a8264b..f0a04b4860 100644 --- a/esphome/core/entity_helpers.py +++ b/esphome/core/entity_helpers.py @@ -246,12 +246,15 @@ def entity_duplicate_validator(platform: str) -> Callable[[ConfigType], ConfigTy "\n to distinguish them" ) - raise cv.Invalid( - f"Duplicate {platform} entity with name '{entity_name}' found{device_prefix}. " - f"{conflict_msg}. " - "Each entity on a device must have a unique name within its platform." - f"{sanitized_msg}" - ) + # Skip duplicate entity name validation when testing_mode is enabled + # This flag is used for grouped component testing + if not CORE.testing_mode: + raise cv.Invalid( + f"Duplicate {platform} entity with name '{entity_name}' found{device_prefix}. " + f"{conflict_msg}. " + "Each entity on a device must have a unique name within its platform." + f"{sanitized_msg}" + ) # Store metadata about this entity entity_metadata: EntityMetadata = { diff --git a/esphome/pins.py b/esphome/pins.py index bcd554a720..9975bad12a 100644 --- a/esphome/pins.py +++ b/esphome/pins.py @@ -118,11 +118,7 @@ class PinRegistry(dict): parent_config = fconf.get_config_for_path(parent_path) final_val_fun(pin_config, parent_config) allow_others = pin_config.get(CONF_ALLOW_OTHER_USES, False) - if ( - count != 1 - and not allow_others - and not CORE.ignore_pin_conflicts - ): + if count != 1 and not allow_others and not CORE.testing_mode: raise cv.Invalid( f"Pin {pin_config[CONF_NUMBER]} is used in multiple places" ) diff --git a/script/test_build_components.py b/script/test_build_components.py index da81465107..fa30b8f5be 100755 --- a/script/test_build_components.py +++ b/script/test_build_components.py @@ -9,7 +9,7 @@ Features: - Analyzes components for shared common bus configs - Groups compatible components together - Merges configs for grouped components -- Uses --ignore-pin-conflicts for grouped tests +- Uses --testing-mode for grouped tests - Maintains backward compatibility with single component testing """ @@ -119,7 +119,7 @@ def run_esphome_test( build_dir: Path, esphome_command: str, continue_on_fail: bool, - use_ignore_pin_conflicts: bool = False, + use_testing_mode: bool = False, ) -> bool: """Run esphome test for a single component. @@ -132,7 +132,7 @@ def run_esphome_test( build_dir: Path to build directory esphome_command: ESPHome command (config/compile) continue_on_fail: Whether to continue on failure - use_ignore_pin_conflicts: Whether to use --ignore-pin-conflicts flag + use_testing_mode: Whether to use --testing-mode flag Returns: True if test passed, False otherwise @@ -157,9 +157,9 @@ def run_esphome_test( "esphome", ] - # Add --ignore-pin-conflicts if needed (must be before subcommand) - if use_ignore_pin_conflicts: - cmd.append("--ignore-pin-conflicts") + # Add --testing-mode if needed (must be before subcommand) + if use_testing_mode: + cmd.append("--testing-mode") # Add substitutions cmd.extend( @@ -184,8 +184,8 @@ def run_esphome_test( # Run command print(f"> [{component}] [{test_name}] [{platform_with_version}]") - if use_ignore_pin_conflicts: - print(" (using --ignore-pin-conflicts)") + if use_testing_mode: + print(" (using --testing-mode)") try: result = subprocess.run(cmd, check=not continue_on_fail) @@ -248,12 +248,12 @@ def run_grouped_test( output_content = base_content.replace("$component_test_file", merged_ref) output_file.write_text(output_content) - # Build esphome command with --ignore-pin-conflicts + # Build esphome command with --testing-mode cmd = [ sys.executable, "-m", "esphome", - "--ignore-pin-conflicts", # Required for grouped tests + "--testing-mode", # Required for grouped tests "-s", "component_name", group_name, @@ -273,7 +273,7 @@ def run_grouped_test( # Run command components_str = ", ".join(components) print(f"> [GROUPED: {components_str}] [{platform_with_version}]") - print(" (using --ignore-pin-conflicts)") + print(" (using --testing-mode)") try: result = subprocess.run(cmd, check=not continue_on_fail)