Repository: aristanetworks/anta
Pull request #1081 (2025-03-11 05:02:23)

refactor(anta.tests): Updated test failure messages
# Description

Updated test failure messages:

1. services
2. snmp
3. system
4. software
5. stp
6. stun
7. vlan
8. vxlan

# Checklist:

- [X] My code follows the style guidelines of this project
- [X] I have performed a self-review of my code
- [X] I have run pre-commit for code linting and typing (`pre-commit run`)
- [ ] I have made corresponding changes to the documentation
- [X] I have added tests that prove my fix is effective or that my feature works
- [X] New and existing unit tests pass locally with my changes (`tox -e testenv`)


sonarqubecloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=aristanetworks_anta&pullRequest=1081) **Quality Gate passed**  
Issues  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 New issues](https://sonarcloud.io/project/issues?id=aristanetworks_anta&pullRequest=1081&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/accepted-16px.png '') [0 Accepted issues](https://sonarcloud.io/project/issues?id=aristanetworks_anta&pullRequest=1081&issueStatuses=ACCEPTED)

Measures  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=aristanetworks_anta&pullRequest=1081&issueStatuses=OPEN,CONFIRMED&sinceLeakPeriod=true)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=aristanetworks_anta&pullRequest=1081&metric=new_coverage&view=list)  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/passed-16px.png '') [0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=aristanetworks_anta&pullRequest=1081&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=aristanetworks_anta&pullRequest=1081)


codspeed-hq[bot]: <!-- __CODSPEED_PERFORMANCE_REPORT_COMMENT__ -->
<!-- __CODSPEED_INSTRUMENTATION_PERFORMANCE_REPORT_COMMENT__ -->

## [CodSpeed Performance Report](https://codspeed.io/aristanetworks/anta/branches/vitthalmagadum%3Afix-failure-msgs)

### Merging #1081 will **not alter performance**

<sub>Comparing <code>vitthalmagadum:fix-failure-msgs</code> (04646bc) with <code>main</code> (d6dee62)</sub>



### Summary

`✅ 22` untouched benchmarks  





Patch:
diff --git a/anta/cli/exec/utils.py b/anta/cli/exec/utils.py
index 3df4b7a5..3258d0be 100644
--- a/anta/cli/exec/utils.py
+++ b/anta/cli/exec/utils.py
@@ -13,6 +13,7 @@ import logging
 from pathlib import Path
 from typing import TYPE_CHECKING, Literal
 
+from asyncssh.misc import HostKeyNotVerifiable
 from click.exceptions import UsageError
 from httpx import ConnectError, HTTPError
 
@@ -97,7 +98,7 @@ async def collect_commands(
             logger.error("Error when collecting commands: %s", str(r))
 
 
-async def collect_show_tech(inv: AntaInventory, root_dir: Path, *, configure: bool, tags: set[str] | None = None, latest: int | None = None) -> None:
+async def collect_show_tech(inv: AntaInventory, root_dir: Path, *, configure: bool, tags: set[str] | None = None, latest: int | None = None) -> None:  # noqa: C901
     """Collect scheduled show-tech on devices."""
 
     async def collect(device: AntaDevice) -> None:
@@ -163,6 +164,11 @@ async def collect_show_tech(inv: AntaInventory, root_dir: Path, *, configure: bo
             await device.copy(sources=filenames, destination=outdir, direction="from")
             logger.info("Collected %s scheduled tech-support from %s", len(filenames), device.name)
 
+        except HostKeyNotVerifiable:
+            logger.error(
+                "Unable to collect tech-support on %s. The host SSH key could not be verified. Make sure it is part of the `known_hosts` file on your machine.",
+                device.name,
+            )
         except (EapiCommandError, HTTPError, ConnectError) as e:
             logger.error("Unable to collect tech-support on %s: %s", device.name, str(e))
 
diff --git a/anta/cli/utils.py b/anta/cli/utils.py
index 508424dd..34b96b3f 100644
--- a/anta/cli/utils.py
+++ b/anta/cli/utils.py
@@ -9,7 +9,7 @@ import enum
 import functools
 import logging
 from pathlib import Path
-from typing import TYPE_CHECKING, Any, Callable
+from typing import TYPE_CHECKING, Any, Callable, Literal
 
 import click
 from yaml import YAMLError
@@ -191,6 +191,14 @@ def core_options(f: Callable[..., Any]) -> Callable[..., Any]:
         required=True,
         type=click.Path(file_okay=True, dir_okay=False, exists=True, readable=True, path_type=Path),
     )
+    @click.option(
+        "--inventory-format",
+        envvar="ANTA_INVENTORY_FORMAT",
+        show_envvar=True,
+        help="Format of the inventory file, either 'yaml' or 'json'",
+        default="yaml",
+        type=click.Choice(["yaml", "json"], case_sensitive=False),
+    )
     @click.pass_context
     @functools.wraps(f)
     def wrapper(
@@ -205,6 +213,7 @@ def core_options(f: Callable[..., Any]) -> Callable[..., Any]:
         timeout: float,
         insecure: bool,
         disable_cache: bool,
+        inventory_format: Literal["json", "yaml"],
         **kwargs: dict[str, Any],
     ) -> Any:
         # If help is invoke somewhere, do not parse inventory
@@ -242,6 +251,7 @@ def core_options(f: Callable[..., Any]) -> Callable[..., Any]:
                 timeout=timeout,
                 insecure=insecure,
                 disable_cache=disable_cache,
+                file_format=inventory_format,
             )
         except (TypeError, ValueError, YAMLError, OSError, InventoryIncorrectSchemaError, InventoryRootKeyError) as e:
             anta_log_exception(e, f"Failed to parse the inventory: {inventory}", logger)
diff --git a/anta/input_models/routing/bgp.py b/anta/input_models/routing/bgp.py
index 5c9226ec..1c9483b3 100644
--- a/anta/input_models/routing/bgp.py
+++ b/anta/input_models/routing/bgp.py
@@ -175,6 +175,10 @@ class BgpPeer(BaseModel):
     """The warning limit for the maximum routes. `0` means no warning.
 
     Optional field in the `VerifyBGPPeerRouteLimit` test. If not provided, the test will not verify the warning limit."""
+    ttl: int | None = Field(default=None, ge=1, le=255)
+    """The Time-To-Live (TTL). Required field in the `VerifyBGPPeerTtlMultiHops` test."""
+    max_ttl_hops: int | None = Field(default=None, ge=1, le=255)
+    """The Max TTL hops. Required field in the `VerifyBGPPeerTtlMultiHops` test."""
 
     def __str__(self) -> str:
         """Return a human-readable string representation of the BgpPeer for reporting."""
diff --git a/anta/input_models/snmp.py b/anta/input_models/snmp.py
index 9475d9cb..d5f14083 100644
--- a/anta/input_models/snmp.py
+++ b/anta/input_models/snmp.py
@@ -124,4 +124,4 @@ class SnmpGroup(BaseModel):
         --------
         - Group: Test_Group Version: v2c
         """
-        return f"Group: {self.group_name}, Version: {self.version}"
+        return f"Group: {self.group_name} Version: {self.version}"
diff --git a/anta/inventory/__init__.py b/anta/inventory/__init__.py
index f98c42f2..a62afacc 100644
--- a/anta/inventory/__init__.py
+++ b/anta/inventory/__init__.py
@@ -8,8 +8,9 @@ from __future__ import annotations
 import asyncio
 import logging
 from ipaddress import ip_address, ip_network
+from json import load as json_load
 from pathlib import Path
-from typing import Any, ClassVar
+from typing import Any, ClassVar, Literal
 
 from pydantic import ValidationError
 from yaml import YAMLError, safe_load
@@ -178,6 +179,7 @@ class AntaInventory(dict[str, AntaDevice]):
         password: str,
         enable_password: str | None = None,
         timeout: float | None = None,
+        file_format: Literal["yaml", "json"] = "yaml",
         *,
         enable: bool = False,
         insecure: bool = False,
@@ -199,6 +201,8 @@ class AntaInventory(dict[str, AntaDevice]):
             Enable password to use if required.
         timeout
             Timeout value in seconds for outgoing API calls.
+        file_format
+            Whether the inventory file is in JSON or YAML.
         enable
             Whether or not the commands need to be run in enable mode towards the devices.
         insecure
@@ -214,6 +218,10 @@ class AntaInventory(dict[str, AntaDevice]):
             Inventory file is not following AntaInventory Schema.
 
         """
+        if file_format not in ["yaml", "json"]:
+            message = f"'{file_format}' is not a valid format for an AntaInventory file. Only 'yaml' and 'json' are supported."
+            raise ValueError(message)
+
         inventory = AntaInventory()
         kwargs: dict[str, Any] = {
             "username": username,
@@ -224,20 +232,12 @@ class AntaInventory(dict[str, AntaDevice]):
             "insecure": insecure,
             "disable_cache": disable_cache,
         }
-        if username is None:
-            message = "'username' is required to create an AntaInventory"
-            logger.error(message)
-            raise ValueError(message)
-        if password is None:
-            message = "'password' is required to create an AntaInventory"
-            logger.error(message)
-            raise ValueError(message)
 
         try:
             filename = Path(filename)
             with filename.open(encoding="UTF-8") as file:
-                data = safe_load(file)
-        except (TypeError, YAMLError, OSError) as e:
+                data = safe_load(file) if file_format == "yaml" else json_load(file)
+        except (TypeError, YAMLError, OSError, ValueError) as e:
             message = f"Unable to parse ANTA Device Inventory file '{filename}'"
             anta_log_exception(e, message, logger)
             raise
diff --git a/anta/inventory/models.py b/anta/inventory/models.py
index 320f5276..493bad71 100644
--- a/anta/inventory/models.py
+++ b/anta/inventory/models.py
@@ -9,14 +9,26 @@ import logging
 import math
 
 import yaml
-from pydantic import BaseModel, ConfigDict, IPvAnyAddress, IPvAnyNetwork
+from pydantic import BaseModel, ConfigDict, FieldSerializationInfo, IPvAnyAddress, IPvAnyNetwork, field_serializer
 
 from anta.custom_types import Hostname, Port
 
 logger = logging.getLogger(__name__)
 
 
-class AntaInventoryHost(BaseModel):
+class AntaInventoryBaseModel(BaseModel):
+    """Pydantic BaseModel for AntaInventory objects."""
+
+    model_config = ConfigDict(extra="forbid")
+
+    # Using check_fields as we plan to use this in the child classes
+    @field_serializer("tags", when_used="json", check_fields=False)
+    def serialize_tags(self, tags: set[str], _info: FieldSerializationInfo) -> list[str]:
+        """Make sure the tags are always dumped in the same order."""
+        return sorted(tags)
+
+
+class AntaInventoryHost(AntaInventoryBaseModel):
     """Host entry of AntaInventoryInput.
 
     Attributes
@@ -34,8 +46,6 @@ class AntaInventoryHost(BaseModel):
 
     """
 
-    model_config = ConfigDict(extra="forbid")
-
     name: str | None = None
     host: Hostname | IPvAnyAddress
     port: Port | None = None
@@ -43,7 +53,7 @@ class AntaInventoryHost(BaseModel):
     disable_cache: bool = False
 
 
-class AntaInventoryNetwork(BaseModel):
+class AntaInventoryNetwork(AntaInventoryBaseModel):
     """Network entry of AntaInventoryInput.
 
     Attributes
@@ -57,14 +67,12 @@ class AntaInventoryNetwork(BaseModel):
 
     """
 
-    model_config = ConfigDict(extra="forbid")
-
     network: IPvAnyNetwork
     tags: set[str] | None = None
     disable_cache: bool = False
 
 
-class AntaInventoryRange(BaseModel):
+class AntaInventoryRange(AntaInventoryBaseModel):
     """IP Range entry of AntaInventoryInput.
 
     Attributes
@@ -80,8 +88,6 @@ class AntaInventoryRange(BaseModel):
 
     """
 
-    model_config = ConfigDict(extra="forbid")
-
     start: IPvAnyAddress
     end: IPvAnyAddress
     tags: set[str] | None = None
@@ -109,4 +115,13 @@ class AntaInventoryInput(BaseModel):
         # This could be improved.
         # https://github.com/pydantic/pydantic/issues/1043
         # Explore if this worth using this: https://github.com/NowanIlfideme/pydantic-yaml
-        return yaml.safe_dump(yaml.safe_load(self.model_dump_json(serialize_as_any=True, exclude_unset=True)), indent=2, width=math.inf)
+        return yaml.safe_dump(yaml.safe_load(self.model_dump_json(serialize_as_any=True, exclude_unset=True)), width=math.inf)
+
+    def to_json(self) -> str:
+        """Return a JSON representation string of this model.
+
+        Returns
+        -------
+            The JSON representation string of this model.
+        """
+        return self.model_dump_json(serialize_as_any=True, exclude_unset=True, indent=2)
diff --git a/docs/snippets/anta_nrfu_help.txt b/docs/snippets/anta_nrfu_help.txt
index 5801f4e3..5500389b 100644
--- a/docs/snippets/anta_nrfu_help.txt
+++ b/docs/snippets/anta_nrfu_help.txt
@@ -28,6 +28,8 @@ Options:
                                   ANTA_DISABLE_CACHE]
   -i, --inventory FILE            Path to the inventory YAML file.  [env var:
                                   ANTA_INVENTORY; required]
+  --inventory-format [yaml|json]  Format of the inventory file, either 'yaml'
+                                  or 'json'  [env var: ANTA_INVENTORY_FORMAT]
   --tags TEXT                     List of tags using comma as separator:
                                   tag1,tag2,tag3.  [env var: ANTA_TAGS]
   -c, --catalog FILE              Path to the test catalog file  [env var:


Test patch:
diff --git a/.github/workflows/code-testing.yml b/.github/workflows/code-testing.yml
index de2e6bc6..84777d68 100644
--- a/.github/workflows/code-testing.yml
+++ b/.github/workflows/code-testing.yml
@@ -43,7 +43,7 @@ jobs:
               - 'docs/**'
               - 'README.md'
   check-requirements:
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
     strategy:
       matrix:
         python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
@@ -62,7 +62,7 @@ jobs:
   # @gmuloc: commenting this out for now
   #missing-documentation:
   #  name: "Warning documentation is missing"
-  #  runs-on: ubuntu-20.04
+  #  runs-on: ubuntu-latest
   #  needs: [file-changes]
   #  if: needs.file-changes.outputs.cli == 'true' && needs.file-changes.outputs.docs == 'false'
   #  steps:
@@ -74,7 +74,7 @@ jobs:
   #          You should update documentation to reflect your change, or maybe not :)
   lint-python:
     name: Check the code style
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
     needs: file-changes
     if: needs.file-changes.outputs.code == 'true'
     steps:
@@ -89,7 +89,7 @@ jobs:
         run: tox -e lint
   type-python:
     name: Check typing
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
     needs: file-changes
     if: needs.file-changes.outputs.code == 'true'
     steps:
@@ -104,7 +104,7 @@ jobs:
         run: tox -e type
   test-python:
     name: Pytest across all supported python versions
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
     needs: [lint-python, type-python]
     strategy:
       matrix:
@@ -138,7 +138,7 @@ jobs:
         run: tox
   test-documentation:
     name: Build offline documentation for testing
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-latest
     needs: [test-python]
     steps:
       - uses: actions/checkout@v4
diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py
index 7522c254..c93fdea7 100644
--- a/anta/tests/routing/bgp.py
+++ b/anta/tests/routing/bgp.py
@@ -131,7 +131,7 @@ class VerifyBGPPeerCount(AntaTest):
 
             # Check if the count matches the expected count
             if address_family.num_peers != peer_count:
-                self.result.is_failure(f"{address_family} - Expected: {address_family.num_peers}, Actual: {peer_count}")
+                self.result.is_failure(f"{address_family} - Peer count mismatch - Expected: {address_family.num_peers} Actual: {peer_count}")
 
 
 class VerifyBGPPeersHealth(AntaTest):
@@ -210,7 +210,7 @@ class VerifyBGPPeersHealth(AntaTest):
             for peer in relevant_peers:
                 # Check if the BGP session is established
                 if peer["state"] != "Established":
-                    self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - Session state is not established - State: {peer['state']}")
+                    self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - Incorrect session state - Expected: Established Actual: {peer['state']}")
                     continue
 
                 # Check if the AFI/SAFI state is negotiated
@@ -223,7 +223,7 @@ class VerifyBGPPeersHealth(AntaTest):
                     inq = peer["peerTcpInfo"]["inputQueueLength"]
                     outq = peer["peerTcpInfo"]["outputQueueLength"]
                     if inq != 0 or outq != 0:
-                        self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}")
+                        self.result.is_failure(f"{address_family} Peer: {peer['peerAddress']} - Session has non-empty message queues - InQ: {inq} OutQ: {outq}")
 
 
 class VerifyBGPSpecificPeers(AntaTest):
@@ -313,7 +313,7 @@ class VerifyBGPSpecificPeers(AntaTest):
 
                 # Check if the BGP session is established
                 if peer_data["state"] != "Established":
-                    self.result.is_failure(f"{address_family} Peer: {peer_ip} - Session state is not established - State: {peer_data['state']}")
+                    self.result.is_failure(f"{address_family} Peer: {peer_ip} - Incorrect session state - Expected: Established Actual: {peer_data['state']}")
                     continue
 
                 # Check if the AFI/SAFI state is negotiated
@@ -329,7 +329,7 @@ class VerifyBGPSpecificPeers(AntaTest):
                     inq = peer_data["peerTcpInfo"]["inputQueueLength"]
                     outq = peer_data["peerTcpInfo"]["outputQueueLength"]
                     if inq != 0 or outq != 0:
-                        self.result.is_failure(f"{address_family} Peer: {peer_ip} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}")
+                        self.result.is_failure(f"{address_family} Peer: {peer_ip} - Session has non-empty message queues - InQ: {inq} OutQ: {outq}")
 
 
 class VerifyBGPPeerSession(AntaTest):
@@ -401,7 +401,7 @@ class VerifyBGPPeerSession(AntaTest):
 
             # Check if the BGP session is established
             if peer_data["state"] != "Established":
-                self.result.is_failure(f"{peer} - Session state is not established - State: {peer_data['state']}")
+                self.result.is_failure(f"{peer} - Incorrect session state - Expected: Established Actual: {peer_data['state']}")
                 continue
 
             # Check the TCP session message queues
@@ -409,7 +409,7 @@ class VerifyBGPPeerSession(AntaTest):
                 inq = peer_data["peerTcpInfo"]["inputQueueLength"]
                 outq = peer_data["peerTcpInfo"]["outputQueueLength"]
                 if inq != 0 or outq != 0:
-                    self.result.is_failure(f"{peer} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}")
+                    self.result.is_failure(f"{peer} - Session has non-empty message queues - InQ: {inq} OutQ: {outq}")
 
 
 class VerifyBGPExchangedRoutes(AntaTest):
@@ -487,7 +487,7 @@ class VerifyBGPExchangedRoutes(AntaTest):
             is_active = route_paths["active"]
             is_valid = route_paths["valid"]
             if not is_active or not is_valid:
-                return f"{peer} {route_type} route: {route} - Valid: {is_valid}, Active: {is_active}"
+                return f"{peer} {route_type} route: {route} - Valid: {is_valid} Active: {is_active}"
             return None
 
         return f"{peer} {route_type} route: {route} - Not found"
@@ -821,7 +821,7 @@ class VerifyBGPPeerMD5Auth(AntaTest):
             state = peer_data.get("state")
             md5_auth_enabled = peer_data.get("md5AuthEnabled")
             if state != "Established":
-                self.result.is_failure(f"{peer} - Session state is not established - State: {state}")
+                self.result.is_failure(f"{peer} - Incorrect session state - Expected: Established Actual: {state}")
             if not md5_auth_enabled:
                 self.result.is_failure(f"{peer} - Session does not have MD5 authentication enabled")
 
@@ -1033,9 +1033,9 @@ class VerifyBGPTimers(AntaTest):
 
             # Check BGP peer timers
             if peer_data["holdTime"] != peer.hold_time:
-                self.result.is_failure(f"{peer} - Hold time mismatch - Expected: {peer.hold_time}, Actual: {peer_data['holdTime']}")
+                self.result.is_failure(f"{peer} - Hold time mismatch - Expected: {peer.hold_time} Actual: {peer_data['holdTime']}")
             if peer_data["keepaliveTime"] != peer.keep_alive_time:
-                self.result.is_failure(f"{peer} - Keepalive time mismatch - Expected: {peer.keep_alive_time}, Actual: {peer_data['keepaliveTime']}")
+                self.result.is_failure(f"{peer} - Keepalive time mismatch - Expected: {peer.keep_alive_time} Actual: {peer_data['keepaliveTime']}")
 
 
 class VerifyBGPPeerDropStats(AntaTest):
@@ -1262,11 +1262,11 @@ class VerifyBgpRouteMaps(AntaTest):
 
             # Verify Inbound route-map
             if inbound_route_map and (inbound_map := peer_data.get("routeMapInbound", "Not Configured")) != inbound_route_map:
-                self.result.is_failure(f"{peer} - Inbound route-map mismatch - Expected: {inbound_route_map}, Actual: {inbound_map}")
+                self.result.is_failure(f"{peer} - Inbound route-map mismatch - Expected: {inbound_route_map} Actual: {inbound_map}")
 
             # Verify Outbound route-map
             if outbound_route_map and (outbound_map := peer_data.get("routeMapOutbound", "Not Configured")) != outbound_route_map:
-                self.result.is_failure(f"{peer} - Outbound route-map mismatch - Expected: {outbound_route_map}, Actual: {outbound_map}")
+                self.result.is_failure(f"{peer} - Outbound route-map mismatch - Expected: {outbound_route_map} Actual: {outbound_map}")
 
 
 class VerifyBGPPeerRouteLimit(AntaTest):
@@ -1340,11 +1340,11 @@ class VerifyBGPPeerRouteLimit(AntaTest):
 
             # Verify maximum routes
             if (actual_maximum_routes := peer_data.get("maxTotalRoutes", "Not Found")) != maximum_routes:
-                self.result.is_failure(f"{peer} - Maximum routes mismatch - Expected: {maximum_routes}, Actual: {actual_maximum_routes}")
+                self.result.is_failure(f"{peer} - Maximum routes mismatch - Expected: {maximum_routes} Actual: {actual_maximum_routes}")
 
             # Verify warning limit if provided. By default, EOS does not have a warning limit and `totalRoutesWarnLimit` is not present in the output.
             if warning_limit is not None and (actual_warning_limit := peer_data.get("totalRoutesWarnLimit", 0)) != warning_limit:
-                self.result.is_failure(f"{peer} - Maximum routes warning limit mismatch - Expected: {warning_limit}, Actual: {actual_warning_limit}")
+                self.result.is_failure(f"{peer} - Maximum routes warning limit mismatch - Expected: {warning_limit} Actual: {actual_warning_limit}")
 
 
 class VerifyBGPPeerGroup(AntaTest):
@@ -1487,7 +1487,7 @@ class VerifyBGPPeerSessionRibd(AntaTest):
 
             # Check if the BGP session is established
             if peer_data["state"] != "Established":
-                self.result.is_failure(f"{peer} - Session state is not established - State: {peer_data['state']}")
+                self.result.is_failure(f"{peer} - Incorrect session state - Expected: Established Actual: {peer_data['state']}")
                 continue
 
             # Check the TCP session message queues
@@ -1495,7 +1495,7 @@ class VerifyBGPPeerSessionRibd(AntaTest):
                 inq_stat = peer_data["peerTcpInfo"]["inputQueueLength"]
                 outq_stat = peer_data["peerTcpInfo"]["outputQueueLength"]
                 if inq_stat != 0 or outq_stat != 0:
-                    self.result.is_failure(f"{peer} - Session has non-empty message queues - InQ: {inq_stat}, OutQ: {outq_stat}")
+                    self.result.is_failure(f"{peer} - Session has non-empty message queues - InQ: {inq_stat} OutQ: {outq_stat}")
 
 
 class VerifyBGPPeersHealthRibd(AntaTest):
@@ -1548,14 +1548,14 @@ class VerifyBGPPeersHealthRibd(AntaTest):
             for peer in peer_list:
                 # Check if the BGP session is established
                 if peer["state"] != "Established":
-                    self.result.is_failure(f"Peer: {peer['peerAddress']} VRF: {vrf} - Session state is not established - State: {peer['state']}")
+                    self.result.is_failure(f"Peer: {peer['peerAddress']} VRF: {vrf} - Incorrect session state - Expected: Established Actual: {peer['state']}")
                     continue
 
                 # Check the TCP session message queues
                 inq = peer["peerTcpInfo"]["inputQueueLength"]
                 outq = peer["peerTcpInfo"]["outputQueueLength"]
                 if self.inputs.check_tcp_queues and (inq != 0 or outq != 0):
-                    self.result.is_failure(f"Peer: {peer['peerAddress']} VRF: {vrf} - Session has non-empty message queues - InQ: {inq}, OutQ: {outq}")
+                    self.result.is_failure(f"Peer: {peer['peerAddress']} VRF: {vrf} - Session has non-empty message queues - InQ: {inq} OutQ: {outq}")
 
 
 class VerifyBGPNlriAcceptance(AntaTest):
@@ -1630,7 +1630,7 @@ class VerifyBGPNlriAcceptance(AntaTest):
                     self.result.is_failure(f"{peer} - {capability} not negotiated")
 
                 if (received := capability_status.get("nlrisReceived")) != (accepted := capability_status.get("nlrisAccepted")):
-                    self.result.is_failure(f"{peer} AFI/SAFI: {capability} - some NLRI were filtered or rejected - Accepted: {accepted} Received: {received}")
+                    self.result.is_failure(f"{peer} AFI/SAFI: {capability} - Some NLRI were filtered or rejected - Accepted: {accepted} Received: {received}")
 
 
 class VerifyBGPRoutePaths(AntaTest):
@@ -1695,7 +1695,7 @@ class VerifyBGPRoutePaths(AntaTest):
         for route in self.inputs.route_entries:
             # Verify if the prefix exists in BGP table
             if not (bgp_routes := get_value(self.instance_commands[0].json_output, f"vrfs..{route.vrf}..bgpRouteEntries..{route.prefix}", separator="..")):
-                self.result.is_failure(f"{route} - prefix not found")
+                self.result.is_failure(f"{route} - Prefix not found")
                 continue
 
             # Iterating over each path.
@@ -1703,7 +1703,7 @@ class VerifyBGPRoutePaths(AntaTest):
                 nexthop = str(path.nexthop)
                 origin = path.origin
                 if not (route_path := get_item(bgp_routes["bgpRoutePaths"], "nextHop", nexthop)):
-                    self.result.is_failure(f"{route} {path} - path not found")
+                    self.result.is_failure(f"{route} {path} - Path not found")
                     continue
 
                 if (actual_origin := get_value(route_path, "routeType.origin")) != origin:
@@ -1773,14 +1773,14 @@ class VerifyBGPRouteECMP(AntaTest):
         for route in self.inputs.route_entries:
             # Verify if the prefix exists in BGP table.
             if not (bgp_route_entry := get_value(self.instance_commands[0].json_output, f"vrfs..{route.vrf}..bgpRouteEntries..{route.prefix}", separator="..")):
-                self.result.is_failure(f"{route} - prefix not found in BGP table")
+                self.result.is_failure(f"{route} - Prefix not found in BGP table")
                 continue
 
             route_paths = iter(bgp_route_entry["bgpRoutePaths"])
             head = next(route_paths, None)
             # Verify if the active ECMP head exists.
             if head is None or not all(head["routeType"][key] for key in ["valid", "active", "ecmpHead"]):
-                self.result.is_failure(f"{route} - valid and active ECMP head not found")
+                self.result.is_failure(f"{route} - Valid and active ECMP head not found")
                 continue
 
             bgp_nexthops = {head["nextHop"]}
@@ -1788,17 +1788,17 @@ class VerifyBGPRouteECMP(AntaTest):
 
             # Verify ECMP count is correct.
             if len(bgp_nexthops) != route.ecmp_count:
-                self.result.is_failure(f"{route} - ECMP count mismatch - Expected: {route.ecmp_count}, Actual: {len(bgp_nexthops)}")
+                self.result.is_failure(f"{route} - ECMP count mismatch - Expected: {route.ecmp_count} Actual: {len(bgp_nexthops)}")
                 continue
 
             # Verify if the prefix exists in routing table.
             if not (route_entry := get_value(self.instance_commands[1].json_output, f"vrfs..{route.vrf}..routes..{route.prefix}", separator="..")):
-                self.result.is_failure(f"{route} - prefix not found in routing table")
+                self.result.is_failure(f"{route} - Prefix not found in routing table")
                 continue
 
             # Verify BGP and RIB nexthops are same.
             if len(bgp_nexthops) != len(route_entry["vias"]):
-                self.result.is_failure(f"{route} - Nexthops count mismatch - BGP: {len(bgp_nexthops)}, RIB: {len(route_entry['vias'])}")
+                self.result.is_failure(f"{route} - Nexthops count mismatch - BGP: {len(bgp_nexthops)} RIB: {len(route_entry['vias'])}")
 
 
 class VerifyBGPRedistribution(AntaTest):
@@ -1893,3 +1893,83 @@ class VerifyBGPRedistribution(AntaTest):
                     failure_msg = self._validate_redistribute_route(str(vrf_data), str(address_family), afi_safi_configs, route_info)
                     for msg in failure_msg:
                         self.result.is_failure(msg)
+
+
+class VerifyBGPPeerTtlMultiHops(AntaTest):
+    """Verifies BGP TTL and max-ttl-hops count for BGP IPv4 peer(s).
+
+    This test performs the following checks for each specified BGP peer:
+
+      1. Verifies the specified BGP peer exists in the BGP configuration.
+      2. Verifies the TTL and max-ttl-hops attribute matches the expected value.
+
+    Expected Results
+    ----------------
+    * Success: The test will pass if all specified peers exist with TTL and max-ttl-hops attributes matching the expected values.
+    * Failure: If any of the following occur:
+        - A specified BGP peer is not found.
+        - A TTL or max-ttl-hops attribute doesn't match the expected value for any peer.
+
+    Examples
+    --------
+    ```yaml
+    anta.tests.routing:
+      bgp:
+        - VerifyBGPPeerTtlMultiHops:
+            bgp_peers:
+                - peer_address: 172.30.11.1
+                  vrf: default
+                  ttl: 3
+                  max_ttl_hops: 3
+                - peer_address: 172.30.11.2
+                  vrf: test
+                  ttl: 30
+                  max_ttl_hops: 30
+    ```
+    """
+
+    categories: ClassVar[list[str]] = ["bgp"]
+    commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show ip bgp neighbors vrf all", revision=2)]
+
+    class Input(AntaTest.Input):
+        """Input model for the VerifyBGPPeerTtlMultiHops test."""
+
+        bgp_peers: list[BgpPeer]
+        """List of IPv4 peer(s)."""
+
+        @field_validator("bgp_peers")
+        @classmethod
+        def validate_bgp_peers(cls, bgp_peers: list[BgpPeer]) -> list[BgpPeer]:
+            """Validate that 'ttl' and 'max_ttl_hops' field is provided in each BGP peer."""
+            for peer in bgp_peers:
+                if peer.ttl is None:
+                    msg = f"{peer} 'ttl' field missing in the input"
+                    raise ValueError(msg)
+                if peer.max_ttl_hops is None:
+                    msg = f"{peer} 'max_ttl_hops' field missing in the input"
+                    raise ValueError(msg)
+
+            return bgp_peers
+
+    @AntaTest.anta_test
+    def test(self) -> None:
+        """Main test function for VerifyBGPPeerTtlMultiHops."""
+        self.result.is_success()
+        command_output = self.instance_commands[0].json_output
+
+        for peer in self.inputs.bgp_peers:
+            peer_ip = str(peer.peer_address)
+            peer_list = get_value(command_output, f"vrfs.{peer.vrf}.peerList", default=[])
+
+            # Check if the peer is found
+            if (peer_details := get_item(peer_list, "peerAddress", peer_ip)) is None:
+                self.result.is_failure(f"{peer} - Not found")
+                continue
+
+            # Verify if the TTL duration matches the expected value.
+            if peer_details.get("ttl") != peer.ttl:
+                self.result.is_failure(f"{peer} - TTL mismatch - Expected: {peer.ttl} Actual: {peer_details.get('ttl')}")
+
+            # Verify if the max-ttl-hops time matches the expected value.
+            if peer_details.get("maxTtlHops") != peer.max_ttl_hops:
+                self.result.is_failure(f"{peer} - Max TTL Hops mismatch - Expected: {peer.max_ttl_hops} Actual: {peer_details.get('maxTtlHops')}")
diff --git a/anta/tests/routing/generic.py b/anta/tests/routing/generic.py
index 338aa615..066d39ce 100644
--- a/anta/tests/routing/generic.py
+++ b/anta/tests/routing/generic.py
@@ -63,7 +63,7 @@ class VerifyRoutingProtocolModel(AntaTest):
         if configured_model == operating_model == self.inputs.model:
             self.result.is_success()
         else:
-            self.result.is_failure(f"routing model is misconfigured: configured: {configured_model} - operating: {operating_model} - expected: {self.inputs.model}")
+            self.result.is_failure(f"Routing model is misconfigured - Expected: {self.inputs.model} Actual: {operating_model}")
 
 
 class VerifyRoutingTableSize(AntaTest):
@@ -112,7 +112,9 @@ class VerifyRoutingTableSize(AntaTest):
         if self.inputs.minimum <= total_routes <= self.inputs.maximum:
             self.result.is_success()
         else:
-            self.result.is_failure(f"Routing table has {total_routes} routes, outside the range of {self.inputs.minimum} to {self.inputs.maximum}")
+            self.result.is_failure(
+                f"Routing table routes are outside the routes range - Expected: {self.inputs.minimum} <= to >= {self.inputs.maximum} Actual: {total_routes}"
+            )
 
 
 class VerifyRoutingTableEntry(AntaTest):
@@ -341,7 +343,7 @@ class VerifyIPv4RouteNextHops(AntaTest):
 
             if entry.strict and expected_nexthops != actual_nexthops:
                 exp_nexthops = ", ".join(expected_nexthops)
-                self.result.is_failure(f"{entry} - List of next-hops not matching - Expected: {exp_nexthops} - Actual: {', '.join(actual_nexthops)}")
+                self.result.is_failure(f"{entry} - List of next-hops not matching - Expected: {exp_nexthops} Actual: {', '.join(actual_nexthops)}")
                 continue
 
             for nexthop in entry.nexthops:
diff --git a/anta/tests/routing/isis.py b/anta/tests/routing/isis.py
index 70574e51..6a73e40a 100644
--- a/anta/tests/routing/isis.py
+++ b/anta/tests/routing/isis.py
@@ -65,9 +65,11 @@ class VerifyISISNeighborState(AntaTest):
                 if not neighbors:
                     continue
                 no_neighbor = False
-                interfaces = [adj["interfaceName"] for neighbor in neighbors.values() for adj in neighbor["adjacencies"] if adj["state"] != "up"]
+                interfaces = [(adj["interfaceName"], adj["state"]) for neighbor in neighbors.values() for adj in neighbor["adjacencies"] if adj["state"] != "up"]
                 for interface in interfaces:
-                    self.result.is_failure(f"Instance: {isis_instance} VRF: {vrf} Interface: {interface} - Adjacency down")
+                    self.result.is_failure(
+                        f"Instance: {isis_instance} VRF: {vrf} Interface: {interface[0]} - Incorrect adjacency state - Expected: up Actual: {interface[1]}"
+                    )
 
         if no_neighbor:
             self.result.is_skipped("No IS-IS neighbor detected")
diff --git a/anta/tests/snmp.py b/anta/tests/snmp.py
index 09bdd768..1d022522 100644
--- a/anta/tests/snmp.py
+++ b/anta/tests/snmp.py
@@ -179,7 +179,7 @@ class VerifySnmpLocation(AntaTest):
         self.result.is_success()
         # Verifies the SNMP location is configured.
         if not (location := get_value(self.instance_commands[0].json_output, "location.location")):
-            self.result.is_failure("SNMP location is not configured.")
+            self.result.is_failure("SNMP location is not configured")
             return
 
         # Verifies the expected SNMP location.
@@ -219,7 +219,7 @@ class VerifySnmpContact(AntaTest):
         self.result.is_success()
         # Verifies the SNMP contact is configured.
         if not (contact := get_value(self.instance_commands[0].json_output, "contact.contact")):
-            self.result.is_failure("SNMP contact is not configured.")
+            self.result.is_failure("SNMP contact is not configured")
             return
 
         # Verifies the expected SNMP contact.
@@ -267,7 +267,7 @@ class VerifySnmpPDUCounters(AntaTest):
 
         # Verify SNMP PDU counters.
         if not (pdu_counters := get_value(command_output, "counters")):
-            self.result.is_failure("SNMP counters not found.")
+            self.result.is_failure("SNMP counters not found")
             return
 
         # In case SNMP PDUs not provided, It will check all the update error counters.
@@ -561,7 +561,7 @@ class VerifySnmpNotificationHost(AntaTest):
 
         # If SNMP is not configured, test fails.
         if not (snmp_hosts := get_value(self.instance_commands[0].json_output, "hosts")):
-            self.result.is_failure("No SNMP host is configured.")
+            self.result.is_failure("No SNMP host is configured")
             return
 
         for host in self.inputs.notification_hosts:
@@ -584,22 +584,22 @@ class VerifySnmpNotificationHost(AntaTest):
 
             # If actual notification type does not match the expected value, test fails.
             if notification_type != (actual_notification_type := get_value(host_details, "notificationType", default_value)):
-                self.result.is_failure(f"{host} - Incorrect notification type - Expected: {notification_type}, Actual: {actual_notification_type}")
+                self.result.is_failure(f"{host} - Incorrect notification type - Expected: {notification_type} Actual: {actual_notification_type}")
 
             # If actual UDP port does not match the expected value, test fails.
             if udp_port != (actual_udp_port := get_value(host_details, "port", default_value)):
-                self.result.is_failure(f"{host} - Incorrect UDP port - Expected: {udp_port}, Actual: {actual_udp_port}")
+                self.result.is_failure(f"{host} - Incorrect UDP port - Expected: {udp_port} Actual: {actual_udp_port}")
 
             user_found = user != (actual_user := get_value(host_details, "v3Params.user", default_value))
             version_user_check = (version == "v3", user_found)
 
             # If SNMP protocol version is v1 or v2c and actual community string does not match the expected value, test fails.
             if version in ["v1", "v2c"] and community_string != (actual_community_string := get_value(host_details, "v1v2cParams.communityString", default_value)):
-                self.result.is_failure(f"{host} Version: {version} - Incorrect community string - Expected: {community_string}, Actual: {actual_community_string}")
+                self.result.is_failure(f"{host} Version: {version} - Incorrect community string - Expected: {community_string} Actual: {actual_community_string}")
 
             # If SNMP protocol version is v3 and actual user does not match the expected value, test fails.
             elif all(version_user_check):
-                self.result.is_failure(f"{host} Version: {version} - Incorrect user - Expected: {user}, Actual: {actual_user}")
+                self.result.is_failure(f"{host} Version: {version} - Incorrect user - Expected: {user} Actual: {actual_user}")
 
 
 class VerifySnmpSourceInterface(AntaTest):
@@ -717,10 +717,10 @@ class VerifySnmpGroup(AntaTest):
                 if group_details.get(f"{view_type}View") == "":
                     self.result.is_failure(f"{group} View: {view_type} - Not configured")
                 elif (act_view := group_details.get(f"{view_type}View")) != expected_view:
-                    self.result.is_failure(f"{group} - Incorrect {view_type.title()} view - Expected: {expected_view}, Actual: {act_view}")
+                    self.result.is_failure(f"{group} - Incorrect {view_type.title()} view - Expected: {expected_view} Actual: {act_view}")
                 elif not group_details.get(f"{view_type}ViewConfig"):
-                    self.result.is_failure(f"{group}, {view_type.title()} View: {expected_view} - Not configured")
+                    self.result.is_failure(f"{group} {view_type.title()} View: {expected_view} - Not configured")
 
             # For version v3, verify that the security model aligns with the expected value.
             if group.version == "v3" and (actual_auth := group_details.get("secModel")) != group.authentication:
-                self.result.is_failure(f"{group} - Incorrect security model - Expected: {group.authentication}, Actual: {actual_auth}")
+                self.result.is_failure(f"{group} - Incorrect security model - Expected: {group.authentication} Actual: {actual_auth}")
diff --git a/anta/tests/software.py b/anta/tests/software.py
index 84228ca3..82517604 100644
--- a/anta/tests/software.py
+++ b/anta/tests/software.py
@@ -131,4 +131,4 @@ class VerifyEOSExtensions(AntaTest):
         if installed_extensions != boot_extensions:
             str_installed_extensions = ", ".join(installed_extensions) if installed_extensions else "Not found"
             str_boot_extensions = ", ".join(boot_extensions) if boot_extensions else "Not found"
-            self.result.is_failure(f"EOS extensions mismatch - Installed: {str_installed_extensions}, Configured: {str_boot_extensions}")
+            self.result.is_failure(f"EOS extensions mismatch - Installed: {str_installed_extensions} Configured: {str_boot_extensions}")
diff --git a/anta/tests/stp.py b/anta/tests/stp.py
index 40f72c18..47dfb9f4 100644
--- a/anta/tests/stp.py
+++ b/anta/tests/stp.py
@@ -281,7 +281,7 @@ class VerifyStpTopologyChanges(AntaTest):
 
         # Verify the STP topology(s).
         if not stp_topologies:
-            self.result.is_failure("STP is not configured.")
+            self.result.is_failure("STP is not configured")
             return
 
         # Verifies the number of changes across all interfaces
diff --git a/anta/tests/stun.py b/anta/tests/stun.py
index ac4f0ea8..da8c2819 100644
--- a/anta/tests/stun.py
+++ b/anta/tests/stun.py
@@ -76,7 +76,7 @@ class VerifyStunClientTranslation(AntaTest):
 
             # If no bindings are found for the STUN client, mark the test as a failure and continue with the next client
             if not bindings:
-                self.result.is_failure(f"{client_input} - STUN client translation not found.")
+                self.result.is_failure(f"{client_input} - STUN client translation not found")
                 continue
 
             # Extract the transaction ID from the bindings
@@ -145,10 +145,10 @@ class VerifyStunServer(AntaTest):
         not_running = command_output.get("pid") == 0
 
         if status_disabled and not_running:
-            self.result.is_failure("STUN server status is disabled and not running.")
+            self.result.is_failure("STUN server status is disabled and not running")
         elif status_disabled:
-            self.result.is_failure("STUN server status is disabled.")
+            self.result.is_failure("STUN server status is disabled")
         elif not_running:
-            self.result.is_failure("STUN server is not running.")
+            self.result.is_failure("STUN server is not running")
         else:
             self.result.is_success()
diff --git a/anta/tests/system.py b/anta/tests/system.py
index 92ca0885..5da3688c 100644
--- a/anta/tests/system.py
+++ b/anta/tests/system.py
@@ -55,7 +55,7 @@ class VerifyUptime(AntaTest):
         self.result.is_success()
         command_output = self.instance_commands[0].json_output
         if command_output["upTime"] < self.inputs.minimum:
-            self.result.is_failure(f"Device uptime is incorrect - Expected: {self.inputs.minimum} Actual: {command_output['upTime']} seconds")
+            self.result.is_failure(f"Device uptime is incorrect - Expected: {self.inputs.minimum}s Actual: {command_output['upTime']}s")
 
 
 class VerifyReloadCause(AntaTest):
diff --git a/anta/tests/vlan.py b/anta/tests/vlan.py
index 09b450ae..25fc9d52 100644
--- a/anta/tests/vlan.py
+++ b/anta/tests/vlan.py
@@ -11,7 +11,7 @@ from typing import TYPE_CHECKING, ClassVar, Literal
 
 from anta.custom_types import DynamicVlanSource, Vlan
 from anta.models import AntaCommand, AntaTest
-from anta.tools import get_failed_logs, get_value
+from anta.tools import get_value
 
 if TYPE_CHECKING:
     from anta.models import AntaTemplate
@@ -55,19 +55,22 @@ class VerifyVlanInternalPolicy(AntaTest):
     @AntaTest.anta_test
     def test(self) -> None:
         """Main test function for VerifyVlanInternalPolicy."""
+        self.result.is_success()
         command_output = self.instance_commands[0].json_output
 
-        keys_to_verify = ["policy", "startVlanId", "endVlanId"]
-        actual_policy_output = {key: get_value(command_output, key) for key in keys_to_verify}
-        expected_policy_output = {"policy": self.inputs.policy, "startVlanId": self.inputs.start_vlan_id, "endVlanId": self.inputs.end_vlan_id}
-
-        # Check if the actual output matches the expected output
-        if actual_policy_output != expected_policy_output:
-            failed_log = "The VLAN internal allocation policy is not configured properly:"
-            failed_log += get_failed_logs(expected_policy_output, actual_policy_output)
-            self.result.is_failure(failed_log)
-        else:
-            self.result.is_success()
+        if (policy := self.inputs.policy) != (act_policy := get_value(command_output, "policy")):
+            self.result.is_failure(f"Incorrect VLAN internal allocation policy configured - Expected: {policy} Actual: {act_policy}")
+            return
+
+        if (start_vlan_id := self.inputs.start_vlan_id) != (act_vlan_id := get_value(command_output, "startVlanId")):
+            self.result.is_failure(
+                f"VLAN internal allocation policy: {self.inputs.policy} - Incorrect start VLAN id configured - Expected: {start_vlan_id} Actual: {act_vlan_id}"
+            )
+
+        if (end_vlan_id := self.inputs.end_vlan_id) != (act_vlan_id := get_value(command_output, "endVlanId")):
+            self.result.is_failure(
+                f"VLAN internal allocation policy: {self.inputs.policy} - Incorrect end VLAN id configured - Expected: {end_vlan_id} Actual: {act_vlan_id}"
+            )
 
 
 class VerifyDynamicVlanSource(AntaTest):
diff --git a/examples/tests.yaml b/examples/tests.yaml
index 5210f3d0..fd1d3e7c 100644
--- a/examples/tests.yaml
+++ b/examples/tests.yaml
@@ -494,6 +494,17 @@ anta.tests.routing.bgp:
           vrf: DEV
         - peer_address: 10.1.255.4
           vrf: DEV
+  - VerifyBGPPeerTtlMultiHops:
+      # Verifies BGP TTL and max-ttl-hops count for BGP IPv4 peer(s).
+      bgp_peers:
+          - peer_address: 172.30.11.1
+            vrf: default
+            ttl: 3
+            max_ttl_hops: 3
+          - peer_address: 172.30.11.2
+            vrf: test
+            ttl: 30
+            max_ttl_hops: 30
   - VerifyBGPPeerUpdateErrors:
       # Verifies BGP update error counters for the provided BGP IPv4 peer(s).
       bgp_peers:
diff --git a/tests/data/test_inventory_large.json b/tests/data/test_inventory_large.json
new file mode 100644
index 00000000..876d9409
--- /dev/null
+++ b/tests/data/test_inventory_large.json
@@ -0,0 +1,207 @@
+{
+  "anta_inventory": {
+    {
+      "hosts": [
+        {
+          "name": "super-spine1",
+          "host": "localhost"
+        },
+        {
+          "name": "super-spine2",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-spine1",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-spine2",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-spine3",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-spine4",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf1a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf1b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf2a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf2b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf3a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf3b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf4a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf4b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf5a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf5b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf6a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf6b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf7a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf7b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf8a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf8b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf9a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf9b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf10a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod1-leaf10b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-spine1",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-spine2",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-spine3",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-spine4",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf1a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf1b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf2a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf2b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf3a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf3b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf4a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf4b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf5a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf5b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf6a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf6b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf7a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf7b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf8a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf8b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf9a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf9b",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf10a",
+          "host": "localhost"
+        },
+        {
+          "name": "pod2-leaf10b",
+          "host": "localhost"
+        }
+      ]
+    }
+}
diff --git a/tests/data/test_inventory_medium.json b/tests/data/test_inventory_medium.json
new file mode 100644
index 00000000..5c4f1473
--- /dev/null
+++ b/tests/data/test_inventory_medium.json
@@ -0,0 +1,30 @@
+{
+  "anta_inventory": {
+    "hosts": [
+      {
+        "name": "spine1",
+        "host": "localhost"
+      },
+      {
+        "name": "spine2",
+        "host": "localhost"
+      },
+      {
+        "name": "leaf1a",
+        "host": "localhost"
+      },
+      {
+        "name": "leaf1b",
+        "host": "localhost"
+      },
+      {
+        "name": "leaf2a",
+        "host": "localhost"
+      },
+      {
+        "name": "leaf2b",
+        "host": "localhost"
+      }
+    ]
+  }
+}
diff --git a/tests/data/test_inventory_with_tags.json b/tests/data/test_inventory_with_tags.json
new file mode 100644
index 00000000..0f0aa7ce
--- /dev/null
+++ b/tests/data/test_inventory_with_tags.json
@@ -0,0 +1,22 @@
+{
+  "anta_inventory": {
+    "hosts": [
+      {
+        "name": "leaf1",
+        "host": "leaf1.anta.arista.com",
+        "tags": ["dc1", "leaf"]
+      },
+      {
+        "name": "leaf2",
+        "host": "leaf2.anta.arista.com",
+        "tags": ["leaf"]
+      },
+      {
+        "name": "spine1",
+        "host": "spine1.anta.arista.com",
+        "tags": ["spine"],
+        "disable_cache": true
+      }
+    ]
+  }
+}
diff --git a/tests/data/test_inventory_with_tags.yml b/tests/data/test_inventory_with_tags.yml
index 16a9df4c..a3eb0c00 100644
--- a/tests/data/test_inventory_with_tags.yml
+++ b/tests/data/test_inventory_with_tags.yml
@@ -3,10 +3,11 @@ anta_inventory:
   hosts:
     - name: leaf1
       host: leaf1.anta.arista.com
-      tags: ["leaf", "dc1"]
+      tags: ["dc1", "leaf"]
     - name: leaf2
       host: leaf2.anta.arista.com
       tags: ["leaf"]
     - name: spine1
       host: spine1.anta.arista.com
       tags: ["spine"]
+      disable_cache: true
diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py
index ee26155f..08266b67 100644
--- a/tests/units/anta_tests/routing/test_bgp.py
+++ b/tests/units/anta_tests/routing/test_bgp.py
@@ -27,6 +27,7 @@ from anta.tests.routing.bgp import (
     VerifyBGPPeerSessionRibd,
     VerifyBGPPeersHealth,
     VerifyBGPPeersHealthRibd,
+    VerifyBGPPeerTtlMultiHops,
     VerifyBGPPeerUpdateErrors,
     VerifyBGPRedistribution,
     VerifyBGPRouteECMP,
@@ -305,7 +306,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: vpn-ipv4 - Expected: 2, Actual: 0",
+                "AFI: vpn-ipv4 - Peer count mismatch - Expected: 2 Actual: 0",
             ],
         },
     },
@@ -374,8 +375,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: evpn - Expected: 3, Actual: 2",
-                "AFI: ipv4 SAFI: unicast VRF: DEV - Expected: 2, Actual: 1",
+                "AFI: evpn - Peer count mismatch - Expected: 3 Actual: 2",
+                "AFI: ipv4 SAFI: unicast VRF: DEV - Peer count mismatch - Expected: 2 Actual: 1",
             ],
         },
     },
@@ -423,9 +424,9 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: evpn - Expected: 2, Actual: 1",
-                "AFI: ipv4 SAFI: unicast VRF: default - Expected: 2, Actual: 1",
-                "AFI: ipv4 SAFI: unicast VRF: DEV - Expected: 2, Actual: 1",
+                "AFI: evpn - Peer count mismatch - Expected: 2 Actual: 1",
+                "AFI: ipv4 SAFI: unicast VRF: default - Peer count mismatch - Expected: 2 Actual: 1",
+                "AFI: ipv4 SAFI: unicast VRF: DEV - Peer count mismatch - Expected: 2 Actual: 1",
             ],
         },
     },
@@ -569,10 +570,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session state is not established - State: Idle",
-                "AFI: ipv4 SAFI: sr-te VRF: MGMT Peer: 10.100.0.12 - Session state is not established - State: Active",
-                "AFI: path-selection Peer: 10.100.0.13 - Session state is not established - State: Idle",
-                "AFI: link-state Peer: 10.100.0.14 - Session state is not established - State: Active",
+                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Incorrect session state - Expected: Established Actual: Idle",
+                "AFI: ipv4 SAFI: sr-te VRF: MGMT Peer: 10.100.0.12 - Incorrect session state - Expected: Established Actual: Active",
+                "AFI: path-selection Peer: 10.100.0.13 - Incorrect session state - Expected: Established Actual: Idle",
+                "AFI: link-state Peer: 10.100.0.14 - Incorrect session state - Expected: Established Actual: Active",
             ],
         },
     },
@@ -687,10 +688,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session has non-empty message queues - InQ: 2, OutQ: 4",
-                "AFI: ipv4 SAFI: sr-te VRF: MGMT Peer: 10.100.0.12 - Session has non-empty message queues - InQ: 5, OutQ: 1",
-                "AFI: path-selection Peer: 10.100.0.13 - Session has non-empty message queues - InQ: 1, OutQ: 1",
-                "AFI: link-state Peer: 10.100.0.14 - Session has non-empty message queues - InQ: 3, OutQ: 2",
+                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session has non-empty message queues - InQ: 2 OutQ: 4",
+                "AFI: ipv4 SAFI: sr-te VRF: MGMT Peer: 10.100.0.12 - Session has non-empty message queues - InQ: 5 OutQ: 1",
+                "AFI: path-selection Peer: 10.100.0.13 - Session has non-empty message queues - InQ: 1 OutQ: 1",
+                "AFI: link-state Peer: 10.100.0.14 - Session has non-empty message queues - InQ: 3 OutQ: 2",
             ],
         },
     },
@@ -843,8 +844,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session state is not established - State: Idle",
-                "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - Session state is not established - State: Idle",
+                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Incorrect session state - Expected: Established Actual: Idle",
+                "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - Incorrect session state - Expected: Established Actual: Idle",
             ],
         },
     },
@@ -972,8 +973,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session has non-empty message queues - InQ: 3, OutQ: 3",
-                "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - Session has non-empty message queues - InQ: 2, OutQ: 2",
+                "AFI: ipv4 SAFI: unicast VRF: default Peer: 10.100.0.12 - Session has non-empty message queues - InQ: 3 OutQ: 3",
+                "AFI: ipv4 SAFI: unicast VRF: MGMT Peer: 10.100.0.14 - Session has non-empty message queues - InQ: 2 OutQ: 2",
             ],
         },
     },
@@ -1452,13 +1453,13 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 172.30.11.1 VRF: default Advertised route: 192.0.254.3/32 - Valid: False, Active: True",
+                "Peer: 172.30.11.1 VRF: default Advertised route: 192.0.254.3/32 - Valid: False Active: True",
                 "Peer: 172.30.11.1 VRF: default Advertised route: 192.0.254.51/32 - Not found",
                 "Peer: 172.30.11.1 VRF: default Received route: 192.0.254.31/32 - Not found",
-                "Peer: 172.30.11.1 VRF: default Received route: 192.0.255.4/32 - Valid: False, Active: False",
+                "Peer: 172.30.11.1 VRF: default Received route: 192.0.255.4/32 - Valid: False Active: False",
                 "Peer: 172.30.11.5 VRF: default Advertised route: 192.0.254.31/32 - Not found",
-                "Peer: 172.30.11.5 VRF: default Advertised route: 192.0.254.5/32 - Valid: False, Active: True",
-                "Peer: 172.30.11.5 VRF: default Received route: 192.0.254.3/32 - Valid: True, Active: False",
+                "Peer: 172.30.11.5 VRF: default Advertised route: 192.0.254.5/32 - Valid: False Active: True",
+                "Peer: 172.30.11.5 VRF: default Received route: 192.0.254.3/32 - Valid: True Active: False",
                 "Peer: 172.30.11.5 VRF: default Received route: 192.0.255.41/32 - Not found",
             ],
         },
@@ -1597,9 +1598,9 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 172.30.11.1 VRF: default Advertised route: 192.0.254.3/32 - Valid: False, Active: True",
+                "Peer: 172.30.11.1 VRF: default Advertised route: 192.0.254.3/32 - Valid: False Active: True",
                 "Peer: 172.30.11.1 VRF: default Advertised route: 192.0.254.51/32 - Not found",
-                "Peer: 172.30.11.5 VRF: default Received route: 192.0.254.3/32 - Valid: True, Active: False",
+                "Peer: 172.30.11.5 VRF: default Received route: 192.0.254.3/32 - Valid: True Active: False",
                 "Peer: 172.30.11.5 VRF: default Received route: 192.0.255.41/32 - Not found",
             ],
         },
@@ -2561,8 +2562,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 172.30.11.1 VRF: default - Session state is not established - State: Idle",
-                "Peer: 172.30.11.10 VRF: MGMT - Session state is not established - State: Idle",
+                "Peer: 172.30.11.1 VRF: default - Incorrect session state - Expected: Established Actual: Idle",
+                "Peer: 172.30.11.10 VRF: MGMT - Incorrect session state - Expected: Established Actual: Idle",
             ],
         },
     },
@@ -3219,9 +3220,9 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 172.30.11.1 VRF: default - Hold time mismatch - Expected: 180, Actual: 160",
-                "Peer: 172.30.11.11 VRF: MGMT - Hold time mismatch - Expected: 180, Actual: 120",
-                "Peer: 172.30.11.11 VRF: MGMT - Keepalive time mismatch - Expected: 60, Actual: 40",
+                "Peer: 172.30.11.1 VRF: default - Hold time mismatch - Expected: 180 Actual: 160",
+                "Peer: 172.30.11.11 VRF: MGMT - Hold time mismatch - Expected: 180 Actual: 120",
+                "Peer: 172.30.11.11 VRF: MGMT - Keepalive time mismatch - Expected: 60 Actual: 40",
             ],
         },
     },
@@ -3831,10 +3832,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN, Actual: RM-MLAG-PEER",
-                "Peer: 10.100.0.8 VRF: default - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT, Actual: RM-MLAG-PEER",
-                "Peer: 10.100.0.10 VRF: MGMT - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN, Actual: RM-MLAG-PEER",
-                "Peer: 10.100.0.10 VRF: MGMT - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT, Actual: RM-MLAG-PEER",
+                "Peer: 10.100.0.8 VRF: default - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN Actual: RM-MLAG-PEER",
+                "Peer: 10.100.0.8 VRF: default - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT Actual: RM-MLAG-PEER",
+                "Peer: 10.100.0.10 VRF: MGMT - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN Actual: RM-MLAG-PEER",
+                "Peer: 10.100.0.10 VRF: MGMT - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT Actual: RM-MLAG-PEER",
             ],
         },
     },
@@ -3874,8 +3875,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN, Actual: RM-MLAG-PEER",
-                "Peer: 10.100.0.10 VRF: MGMT - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN, Actual: RM-MLAG-PEER",
+                "Peer: 10.100.0.8 VRF: default - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN Actual: RM-MLAG-PEER",
+                "Peer: 10.100.0.10 VRF: MGMT - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN Actual: RM-MLAG-PEER",
             ],
         },
     },
@@ -3911,10 +3912,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN, Actual: Not Configured",
-                "Peer: 10.100.0.8 VRF: default - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT, Actual: Not Configured",
-                "Peer: 10.100.0.10 VRF: MGMT - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN, Actual: Not Configured",
-                "Peer: 10.100.0.10 VRF: MGMT - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT, Actual: Not Configured",
+                "Peer: 10.100.0.8 VRF: default - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN Actual: Not Configured",
+                "Peer: 10.100.0.8 VRF: default - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT Actual: Not Configured",
+                "Peer: 10.100.0.10 VRF: MGMT - Inbound route-map mismatch - Expected: RM-MLAG-PEER-IN Actual: Not Configured",
+                "Peer: 10.100.0.10 VRF: MGMT - Outbound route-map mismatch - Expected: RM-MLAG-PEER-OUT Actual: Not Configured",
             ],
         },
     },
@@ -4072,10 +4073,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Maximum routes mismatch - Expected: 12000, Actual: 13000",
-                "Peer: 10.100.0.8 VRF: default - Maximum routes warning limit mismatch - Expected: 10000, Actual: 11000",
-                "Peer: 10.100.0.9 VRF: MGMT - Maximum routes mismatch - Expected: 10000, Actual: 11000",
-                "Peer: 10.100.0.9 VRF: MGMT - Maximum routes warning limit mismatch - Expected: 9000, Actual: 10000",
+                "Peer: 10.100.0.8 VRF: default - Maximum routes mismatch - Expected: 12000 Actual: 13000",
+                "Peer: 10.100.0.8 VRF: default - Maximum routes warning limit mismatch - Expected: 10000 Actual: 11000",
+                "Peer: 10.100.0.9 VRF: MGMT - Maximum routes mismatch - Expected: 10000 Actual: 11000",
+                "Peer: 10.100.0.9 VRF: MGMT - Maximum routes warning limit mismatch - Expected: 9000 Actual: 10000",
             ],
         },
     },
@@ -4113,8 +4114,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Maximum routes warning limit mismatch - Expected: 10000, Actual: 0",
-                "Peer: 10.100.0.9 VRF: MGMT - Maximum routes warning limit mismatch - Expected: 9000, Actual: 0",
+                "Peer: 10.100.0.8 VRF: default - Maximum routes warning limit mismatch - Expected: 10000 Actual: 0",
+                "Peer: 10.100.0.9 VRF: MGMT - Maximum routes warning limit mismatch - Expected: 9000 Actual: 0",
             ],
         },
     },
@@ -4278,8 +4279,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Session state is not established - State: Active",
-                "Peer: 10.100.0.9 VRF: MGMT - Session state is not established - State: Active",
+                "Peer: 10.100.0.8 VRF: default - Incorrect session state - Expected: Established Actual: Active",
+                "Peer: 10.100.0.9 VRF: MGMT - Incorrect session state - Expected: Established Actual: Active",
             ],
         },
     },
@@ -4325,7 +4326,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Session has non-empty message queues - InQ: 5, OutQ: 10",
+                "Peer: 10.100.0.8 VRF: default - Session has non-empty message queues - InQ: 5 OutQ: 10",
             ],
         },
     },
@@ -4677,8 +4678,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Session state is not established - State: Active",
-                "Peer: 10.100.0.9 VRF: MGMT - Session state is not established - State: Active",
+                "Peer: 10.100.0.8 VRF: default - Incorrect session state - Expected: Established Actual: Active",
+                "Peer: 10.100.0.9 VRF: MGMT - Incorrect session state - Expected: Established Actual: Active",
             ],
         },
     },
@@ -4724,7 +4725,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Session has non-empty message queues - InQ: 5, OutQ: 10",
+                "Peer: 10.100.0.8 VRF: default - Session has non-empty message queues - InQ: 5 OutQ: 10",
             ],
         },
     },
@@ -4841,8 +4842,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Session state is not established - State: Active",
-                "Peer: 10.100.0.9 VRF: MGMT - Session state is not established - State: Active",
+                "Peer: 10.100.0.8 VRF: default - Incorrect session state - Expected: Established Actual: Active",
+                "Peer: 10.100.0.9 VRF: MGMT - Incorrect session state - Expected: Established Actual: Active",
             ],
         },
     },
@@ -4883,7 +4884,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default - Session has non-empty message queues - InQ: 5, OutQ: 10",
+                "Peer: 10.100.0.8 VRF: default - Session has non-empty message queues - InQ: 5 OutQ: 10",
             ],
         },
     },
@@ -5145,10 +5146,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Peer: 10.100.0.8 VRF: default AFI/SAFI: ipv4Unicast - some NLRI were filtered or rejected - Accepted: 16 Received: 17",
-                "Peer: 10.100.0.8 VRF: default AFI/SAFI: l2VpnEvpn - some NLRI were filtered or rejected - Accepted: 56 Received: 58",
-                "Peer: 10.100.4.5 VRF: MGMT AFI/SAFI: ipv4Unicast - some NLRI were filtered or rejected - Accepted: 14 Received: 15",
-                "Peer: 10.100.4.5 VRF: MGMT AFI/SAFI: l2VpnEvpn - some NLRI were filtered or rejected - Accepted: 56 Received: 59",
+                "Peer: 10.100.0.8 VRF: default AFI/SAFI: ipv4Unicast - Some NLRI were filtered or rejected - Accepted: 16 Received: 17",
+                "Peer: 10.100.0.8 VRF: default AFI/SAFI: l2VpnEvpn - Some NLRI were filtered or rejected - Accepted: 56 Received: 58",
+                "Peer: 10.100.4.5 VRF: MGMT AFI/SAFI: ipv4Unicast - Some NLRI were filtered or rejected - Accepted: 14 Received: 15",
+                "Peer: 10.100.4.5 VRF: MGMT AFI/SAFI: l2VpnEvpn - Some NLRI were filtered or rejected - Accepted: 56 Received: 59",
             ],
         },
     },
@@ -5344,10 +5345,10 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Prefix: 10.100.0.128/31 VRF: default Next-hop: 10.100.0.10 Origin: Incomplete - path not found",
-                "Prefix: 10.100.0.128/31 VRF: default Next-hop: 10.100.4.5 Origin: Igp - path not found",
-                "Prefix: 10.100.0.130/31 VRF: MGMT Next-hop: 10.100.0.8 Origin: Incomplete - path not found",
-                "Prefix: 10.100.0.130/31 VRF: MGMT Next-hop: 10.100.0.10 Origin: Incomplete - path not found",
+                "Prefix: 10.100.0.128/31 VRF: default Next-hop: 10.100.0.10 Origin: Incomplete - Path not found",
+                "Prefix: 10.100.0.128/31 VRF: default Next-hop: 10.100.4.5 Origin: Igp - Path not found",
+                "Prefix: 10.100.0.130/31 VRF: MGMT Next-hop: 10.100.0.8 Origin: Incomplete - Path not found",
+                "Prefix: 10.100.0.130/31 VRF: MGMT Next-hop: 10.100.0.10 Origin: Incomplete - Path not found",
             ],
         },
     },
@@ -5373,7 +5374,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Prefix: 10.100.0.128/31 VRF: default - prefix not found", "Prefix: 10.100.0.130/31 VRF: MGMT - prefix not found"],
+            "messages": ["Prefix: 10.100.0.128/31 VRF: default - Prefix not found", "Prefix: 10.100.0.130/31 VRF: MGMT - Prefix not found"],
         },
     },
     {
@@ -5507,7 +5508,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"route_entries": [{"prefix": "10.111.124.0/24", "vrf": "default", "ecmp_count": 2}]},
-        "expected": {"result": "failure", "messages": ["Prefix: 10.111.124.0/24 VRF: default - prefix not found in BGP table"]},
+        "expected": {"result": "failure", "messages": ["Prefix: 10.111.124.0/24 VRF: default - Prefix not found in BGP table"]},
     },
     {
         "name": "failure-valid-active-ecmp-head-not-found",
@@ -5577,7 +5578,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"route_entries": [{"prefix": "10.111.134.0/24", "vrf": "default", "ecmp_count": 2}]},
-        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - valid and active ECMP head not found"]},
+        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - Valid and active ECMP head not found"]},
     },
     {
         "name": "failure-ecmp-count-mismatch",
@@ -5647,7 +5648,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"route_entries": [{"prefix": "10.111.134.0/24", "vrf": "default", "ecmp_count": 2}]},
-        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - ECMP count mismatch - Expected: 2, Actual: 1"]},
+        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - ECMP count mismatch - Expected: 2 Actual: 1"]},
     },
     {
         "name": "failure-prefix-not-found-routing-table",
@@ -5717,7 +5718,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"route_entries": [{"prefix": "10.111.134.0/24", "vrf": "default", "ecmp_count": 2}]},
-        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - prefix not found in routing table"]},
+        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - Prefix not found in routing table"]},
     },
     {
         "name": "failure-nexthops-mismatch",
@@ -5787,7 +5788,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"route_entries": [{"prefix": "10.111.134.0/24", "vrf": "default", "ecmp_count": 2}]},
-        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - Nexthops count mismatch - BGP: 2, RIB: 1"]},
+        "expected": {"result": "failure", "messages": ["Prefix: 10.111.134.0/24 VRF: default - Nexthops count mismatch - BGP: 2 RIB: 1"]},
     },
     {
         "name": "success",
@@ -6118,4 +6119,204 @@ DATA: list[dict[str, Any]] = [
             ],
         },
     },
+    {
+        "name": "success",
+        "test": VerifyBGPPeerTtlMultiHops,
+        "eos_data": [
+            {
+                "vrfs": {
+                    "default": {
+                        "peerList": [
+                            {
+                                "peerAddress": "10.111.0.1",
+                                "ttl": 2,
+                                "maxTtlHops": 2,
+                            },
+                            {
+                                "peerAddress": "10.111.0.2",
+                                "ttl": 1,
+                                "maxTtlHops": 1,
+                            },
+                        ]
+                    },
+                    "Test": {"peerList": [{"peerAddress": "10.111.0.3", "ttl": 255, "maxTtlHops": 255}]},
+                }
+            }
+        ],
+        "inputs": {
+            "bgp_peers": [
+                {
+                    "peer_address": "10.111.0.1",
+                    "vrf": "default",
+                    "ttl": 2,
+                    "max_ttl_hops": 2,
+                },
+                {
+                    "peer_address": "10.111.0.2",
+                    "vrf": "default",
+                    "ttl": 1,
+                    "max_ttl_hops": 1,
+                },
+                {
+                    "peer_address": "10.111.0.3",
+                    "vrf": "Test",
+                    "ttl": 255,
+                    "max_ttl_hops": 255,
+                },
+            ]
+        },
+        "expected": {"result": "success"},
+    },
+    {
+        "name": "failure-peer-not-found",
+        "test": VerifyBGPPeerTtlMultiHops,
+        "eos_data": [
+            {
+                "vrfs": {
+                    "default": {
+                        "peerList": [
+                            {
+                                "peerAddress": "10.111.0.4",
+                                "ttl": 2,
+                                "maxTtlHops": 2,
+                            },
+                            {
+                                "peerAddress": "10.111.0.5",
+                                "ttl": 1,
+                                "maxTtlHops": 1,
+                            },
+                        ]
+                    },
+                    "Test": {"peerList": [{"peerAddress": "10.111.0.6", "ttl": 255, "maxTtlHops": 255}]},
+                }
+            }
+        ],
+        "inputs": {
+            "bgp_peers": [
+                {
+                    "peer_address": "10.111.0.1",
+                    "vrf": "default",
+                    "ttl": 2,
+                    "max_ttl_hops": 2,
+                },
+                {
+                    "peer_address": "10.111.0.2",
+                    "vrf": "Test",
+                    "ttl": 255,
+                    "max_ttl_hops": 255,
+                },
+            ]
+        },
+        "expected": {"result": "failure", "messages": ["Peer: 10.111.0.1 VRF: default - Not found", "Peer: 10.111.0.2 VRF: Test - Not found"]},
+    },
+    {
+        "name": "failure-ttl-time-mismatch",
+        "test": VerifyBGPPeerTtlMultiHops,
+        "eos_data": [
+            {
+                "vrfs": {
+                    "default": {
+                        "peerList": [
+                            {
+                                "peerAddress": "10.111.0.1",
+                                "ttl": 12,
+                                "maxTtlHops": 2,
+                            },
+                            {
+                                "peerAddress": "10.111.0.2",
+                                "ttl": 120,
+                                "maxTtlHops": 1,
+                            },
+                        ]
+                    },
+                    "Test": {"peerList": [{"peerAddress": "10.111.0.3", "ttl": 205, "maxTtlHops": 255}]},
+                }
+            }
+        ],
+        "inputs": {
+            "bgp_peers": [
+                {
+                    "peer_address": "10.111.0.1",
+                    "vrf": "default",
+                    "ttl": 2,
+                    "max_ttl_hops": 2,
+                },
+                {
+                    "peer_address": "10.111.0.2",
+                    "vrf": "default",
+                    "ttl": 1,
+                    "max_ttl_hops": 1,
+                },
+                {
+                    "peer_address": "10.111.0.3",
+                    "vrf": "Test",
+                    "ttl": 255,
+                    "max_ttl_hops": 255,
+                },
+            ]
+        },
+        "expected": {
+            "result": "failure",
+            "messages": [
+                "Peer: 10.111.0.1 VRF: default - TTL mismatch - Expected: 2 Actual: 12",
+                "Peer: 10.111.0.2 VRF: default - TTL mismatch - Expected: 1 Actual: 120",
+                "Peer: 10.111.0.3 VRF: Test - TTL mismatch - Expected: 255 Actual: 205",
+            ],
+        },
+    },
+    {
+        "name": "failure-max-ttl-hops-mismatch",
+        "test": VerifyBGPPeerTtlMultiHops,
+        "eos_data": [
+            {
+                "vrfs": {
+                    "default": {
+                        "peerList": [
+                            {
+                                "peerAddress": "10.111.0.1",
+                                "ttl": 2,
+                                "maxTtlHops": 12,
+                            },
+                            {
+                                "peerAddress": "10.111.0.2",
+                                "ttl": 1,
+                                "maxTtlHops": 100,
+                            },
+                        ]
+                    },
+                    "Test": {"peerList": [{"peerAddress": "10.111.0.3", "ttl": 255, "maxTtlHops": 205}]},
+                }
+            }
+        ],
+        "inputs": {
+            "bgp_peers": [
+                {
+                    "peer_address": "10.111.0.1",
+                    "vrf": "default",
+                    "ttl": 2,
+                    "max_ttl_hops": 2,
+                },
+                {
+                    "peer_address": "10.111.0.2",
+                    "vrf": "default",
+                    "ttl": 1,
+                    "max_ttl_hops": 1,
+                },
+                {
+                    "peer_address": "10.111.0.3",
+                    "vrf": "Test",
+                    "ttl": 255,
+                    "max_ttl_hops": 255,
+                },
+            ]
+        },
+        "expected": {
+            "result": "failure",
+            "messages": [
+                "Peer: 10.111.0.1 VRF: default - Max TTL Hops mismatch - Expected: 2 Actual: 12",
+                "Peer: 10.111.0.2 VRF: default - Max TTL Hops mismatch - Expected: 1 Actual: 100",
+                "Peer: 10.111.0.3 VRF: Test - Max TTL Hops mismatch - Expected: 255 Actual: 205",
+            ],
+        },
+    },
 ]
diff --git a/tests/units/anta_tests/routing/test_generic.py b/tests/units/anta_tests/routing/test_generic.py
index 57ad584a..2e67f91d 100644
--- a/tests/units/anta_tests/routing/test_generic.py
+++ b/tests/units/anta_tests/routing/test_generic.py
@@ -27,14 +27,14 @@ DATA: list[dict[str, Any]] = [
         "test": VerifyRoutingProtocolModel,
         "eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "ribd", "operatingProtoModel": "ribd"}}],
         "inputs": {"model": "multi-agent"},
-        "expected": {"result": "failure", "messages": ["routing model is misconfigured: configured: ribd - operating: ribd - expected: multi-agent"]},
+        "expected": {"result": "failure", "messages": ["Routing model is misconfigured - Expected: multi-agent Actual: ribd"]},
     },
     {
         "name": "failure-mismatch-operating-model",
         "test": VerifyRoutingProtocolModel,
         "eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "multi-agent", "operatingProtoModel": "ribd"}}],
         "inputs": {"model": "multi-agent"},
-        "expected": {"result": "failure", "messages": ["routing model is misconfigured: configured: multi-agent - operating: ribd - expected: multi-agent"]},
+        "expected": {"result": "failure", "messages": ["Routing model is misconfigured - Expected: multi-agent Actual: ribd"]},
     },
     {
         "name": "success",
@@ -68,7 +68,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"minimum": 42, "maximum": 666},
-        "expected": {"result": "failure", "messages": ["Routing table has 1000 routes, outside the range of 42 to 666"]},
+        "expected": {"result": "failure", "messages": ["Routing table routes are outside the routes range - Expected: 42 <= to >= 666 Actual: 1000"]},
     },
     {
         "name": "success",
@@ -474,9 +474,9 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Prefix: 10.10.0.1/32 VRF: default - List of next-hops not matching - Expected: 10.100.0.10, 10.100.0.11, 10.100.0.8 - "
+                "Prefix: 10.10.0.1/32 VRF: default - List of next-hops not matching - Expected: 10.100.0.10, 10.100.0.11, 10.100.0.8 "
                 "Actual: 10.100.0.10, 10.100.0.8",
-                "Prefix: 10.100.0.128/31 VRF: MGMT - List of next-hops not matching - Expected: 10.100.0.10, 10.100.0.8 - Actual: 10.100.0.11, 10.100.0.8",
+                "Prefix: 10.100.0.128/31 VRF: MGMT - List of next-hops not matching - Expected: 10.100.0.10, 10.100.0.8 Actual: 10.100.0.11, 10.100.0.8",
             ],
         },
     },
diff --git a/tests/units/anta_tests/routing/test_isis.py b/tests/units/anta_tests/routing/test_isis.py
index aaa77b24..8a36d824 100644
--- a/tests/units/anta_tests/routing/test_isis.py
+++ b/tests/units/anta_tests/routing/test_isis.py
@@ -182,7 +182,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": None,
         "expected": {
             "result": "failure",
-            "messages": ["Instance: CORE-ISIS VRF: default Interface: Ethernet1 - Adjacency down"],
+            "messages": ["Instance: CORE-ISIS VRF: default Interface: Ethernet1 - Incorrect adjacency state - Expected: up Actual: down"],
         },
     },
     {
@@ -249,7 +249,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": {"check_all_vrfs": True},
         "expected": {
             "result": "failure",
-            "messages": ["Instance: CORE-ISIS VRF: customer Interface: Ethernet2 - Adjacency down"],
+            "messages": ["Instance: CORE-ISIS VRF: customer Interface: Ethernet2 - Incorrect adjacency state - Expected: up Actual: down"],
         },
     },
     {
diff --git a/tests/units/anta_tests/test_snmp.py b/tests/units/anta_tests/test_snmp.py
index 48c6bbb1..255443d9 100644
--- a/tests/units/anta_tests/test_snmp.py
+++ b/tests/units/anta_tests/test_snmp.py
@@ -123,7 +123,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": {"location": "New York"},
         "expected": {
             "result": "failure",
-            "messages": ["SNMP location is not configured."],
+            "messages": ["SNMP location is not configured"],
         },
     },
     {
@@ -162,7 +162,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": {"contact": "Bob@example.com"},
         "expected": {
             "result": "failure",
-            "messages": ["SNMP contact is not configured."],
+            "messages": ["SNMP contact is not configured"],
         },
     },
     {
@@ -208,7 +208,7 @@ DATA: list[dict[str, Any]] = [
             }
         ],
         "inputs": {},
-        "expected": {"result": "failure", "messages": ["SNMP counters not found."]},
+        "expected": {"result": "failure", "messages": ["SNMP counters not found"]},
     },
     {
         "name": "failure-incorrect-counters",
@@ -297,7 +297,7 @@ DATA: list[dict[str, Any]] = [
             }
         ],
         "inputs": {},
-        "expected": {"result": "failure", "messages": ["SNMP counters not found."]},
+        "expected": {"result": "failure", "messages": ["SNMP counters not found"]},
     },
     {
         "name": "failure-incorrect-counters",
@@ -580,7 +580,7 @@ DATA: list[dict[str, Any]] = [
                 {"hostname": "192.168.1.101", "vrf": "default", "notification_type": "trap", "version": "v2c", "udp_port": 162, "community_string": "public"},
             ]
         },
-        "expected": {"result": "failure", "messages": ["No SNMP host is configured."]},
+        "expected": {"result": "failure", "messages": ["No SNMP host is configured"]},
     },
     {
         "name": "failure-details-host-not-found",
@@ -641,8 +641,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Host: 192.168.1.100 VRF: default - Incorrect notification type - Expected: inform, Actual: trap",
-                "Host: 192.168.1.101 VRF: default - Incorrect notification type - Expected: trap, Actual: inform",
+                "Host: 192.168.1.100 VRF: default - Incorrect notification type - Expected: inform Actual: trap",
+                "Host: 192.168.1.101 VRF: default - Incorrect notification type - Expected: trap Actual: inform",
             ],
         },
     },
@@ -680,8 +680,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Host: 192.168.1.100 VRF: default - Incorrect UDP port - Expected: 162, Actual: 163",
-                "Host: 192.168.1.101 VRF: default - Incorrect UDP port - Expected: 162, Actual: 164",
+                "Host: 192.168.1.100 VRF: default - Incorrect UDP port - Expected: 162 Actual: 163",
+                "Host: 192.168.1.101 VRF: default - Incorrect UDP port - Expected: 162 Actual: 164",
             ],
         },
     },
@@ -719,8 +719,8 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Host: 192.168.1.100 VRF: default Version: v1 - Incorrect community string - Expected: public, Actual: private",
-                "Host: 192.168.1.101 VRF: default Version: v2c - Incorrect community string - Expected: public, Actual: private",
+                "Host: 192.168.1.100 VRF: default Version: v1 - Incorrect community string - Expected: public Actual: private",
+                "Host: 192.168.1.101 VRF: default Version: v2c - Incorrect community string - Expected: public Actual: private",
             ],
         },
     },
@@ -746,7 +746,7 @@ DATA: list[dict[str, Any]] = [
                 {"hostname": "192.168.1.100", "vrf": "default", "notification_type": "trap", "version": "v3", "udp_port": 162, "user": "public"},
             ]
         },
-        "expected": {"result": "failure", "messages": ["Host: 192.168.1.100 VRF: default Version: v3 - Incorrect user - Expected: public, Actual: private"]},
+        "expected": {"result": "failure", "messages": ["Host: 192.168.1.100 VRF: default Version: v3 - Incorrect user - Expected: public Actual: private"]},
     },
     {
         "name": "success",
@@ -920,14 +920,14 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Group: Group1, Version: v1 - Incorrect Read view - Expected: group_read_1, Actual: group_read",
-                "Group: Group1, Version: v1 - Incorrect Write view - Expected: group_write_1, Actual: group_write",
-                "Group: Group1, Version: v1 - Incorrect Notify view - Expected: group_notify_1, Actual: group_notify",
-                "Group: Group2, Version: v2c - Incorrect Read view - Expected: group_read_2, Actual: group_read",
-                "Group: Group2, Version: v2c - Incorrect Notify view - Expected: group_notify_2, Actual: group_notify",
-                "Group: Group3, Version: v3 - Incorrect Read view - Expected: group_read_3, Actual: group_read",
-                "Group: Group3, Version: v3 - Incorrect Write view - Expected: group_write_3, Actual: group_write",
-                "Group: Group3, Version: v3 - Incorrect Notify view - Expected: group_notify_3, Actual: group_notify",
+                "Group: Group1 Version: v1 - Incorrect Read view - Expected: group_read_1 Actual: group_read",
+                "Group: Group1 Version: v1 - Incorrect Write view - Expected: group_write_1 Actual: group_write",
+                "Group: Group1 Version: v1 - Incorrect Notify view - Expected: group_notify_1 Actual: group_notify",
+                "Group: Group2 Version: v2c - Incorrect Read view - Expected: group_read_2 Actual: group_read",
+                "Group: Group2 Version: v2c - Incorrect Notify view - Expected: group_notify_2 Actual: group_notify",
+                "Group: Group3 Version: v3 - Incorrect Read view - Expected: group_read_3 Actual: group_read",
+                "Group: Group3 Version: v3 - Incorrect Write view - Expected: group_write_3 Actual: group_write",
+                "Group: Group3 Version: v3 - Incorrect Notify view - Expected: group_notify_3 Actual: group_notify",
             ],
         },
     },
@@ -995,14 +995,14 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Group: Group1, Version: v1, Read View: group_read - Not configured",
-                "Group: Group1, Version: v1, Write View: group_write - Not configured",
-                "Group: Group1, Version: v1, Notify View: group_notify - Not configured",
-                "Group: Group2, Version: v2c, Read View: group_read - Not configured",
-                "Group: Group2, Version: v2c, Write View: group_write - Not configured",
-                "Group: Group2, Version: v2c, Notify View: group_notify - Not configured",
-                "Group: Group3, Version: v3, Write View: group_write - Not configured",
-                "Group: Group3, Version: v3, Notify View: group_notify - Not configured",
+                "Group: Group1 Version: v1 Read View: group_read - Not configured",
+                "Group: Group1 Version: v1 Write View: group_write - Not configured",
+                "Group: Group1 Version: v1 Notify View: group_notify - Not configured",
+                "Group: Group2 Version: v2c Read View: group_read - Not configured",
+                "Group: Group2 Version: v2c Write View: group_write - Not configured",
+                "Group: Group2 Version: v2c Notify View: group_notify - Not configured",
+                "Group: Group3 Version: v3 Write View: group_write - Not configured",
+                "Group: Group3 Version: v3 Notify View: group_notify - Not configured",
             ],
         },
     },
@@ -1035,9 +1035,9 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Group: Group1, Version: v1 - Not configured",
-                "Group: Group2, Version: v2c - Not configured",
-                "Group: Group3, Version: v3 - Not configured",
+                "Group: Group1 Version: v1 - Not configured",
+                "Group: Group2 Version: v2c - Not configured",
+                "Group: Group3 Version: v3 - Not configured",
             ],
         },
     },
@@ -1078,7 +1078,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Group: Group3, Version: v3 - Incorrect security model - Expected: v3Priv, Actual: v3Auth",
+                "Group: Group3 Version: v3 - Incorrect security model - Expected: v3Priv Actual: v3Auth",
             ],
         },
     },
@@ -1106,7 +1106,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Group: Group3, Version: v3 View: write - Not configured",
+                "Group: Group3 Version: v3 View: write - Not configured",
             ],
         },
     },
diff --git a/tests/units/anta_tests/test_software.py b/tests/units/anta_tests/test_software.py
index 0bf88b83..217cfff8 100644
--- a/tests/units/anta_tests/test_software.py
+++ b/tests/units/anta_tests/test_software.py
@@ -145,7 +145,7 @@ DATA: list[dict[str, Any]] = [
             {"extensions": []},
         ],
         "inputs": None,
-        "expected": {"result": "failure", "messages": ["EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix, Configured: Not found"]},
+        "expected": {"result": "failure", "messages": ["EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix Configured: Not found"]},
     },
     {
         "name": "failure-multiple-extensions",
@@ -194,7 +194,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix, Configured: AristaCloudGateway-1.0.1-1.swix, EOS-4.33.0F-NDRSensor.swix"
+                "EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix Configured: AristaCloudGateway-1.0.1-1.swix, EOS-4.33.0F-NDRSensor.swix"
             ],
         },
     },
diff --git a/tests/units/anta_tests/test_stp.py b/tests/units/anta_tests/test_stp.py
index 3dbd8c5d..539c5e92 100644
--- a/tests/units/anta_tests/test_stp.py
+++ b/tests/units/anta_tests/test_stp.py
@@ -574,7 +574,7 @@ DATA: list[dict[str, Any]] = [
             },
         ],
         "inputs": {"threshold": 10},
-        "expected": {"result": "failure", "messages": ["STP is not configured."]},
+        "expected": {"result": "failure", "messages": ["STP is not configured"]},
     },
     {
         "name": "success",
diff --git a/tests/units/anta_tests/test_stun.py b/tests/units/anta_tests/test_stun.py
index 1001af8a..0d1363c0 100644
--- a/tests/units/anta_tests/test_stun.py
+++ b/tests/units/anta_tests/test_stun.py
@@ -108,7 +108,7 @@ DATA: list[dict[str, Any]] = [
         },
         "expected": {
             "result": "failure",
-            "messages": ["Client 100.64.3.2 Port: 4500 - STUN client translation not found.", "Client 172.18.3.2 Port: 4500 - STUN client translation not found."],
+            "messages": ["Client 100.64.3.2 Port: 4500 - STUN client translation not found", "Client 172.18.3.2 Port: 4500 - STUN client translation not found"],
         },
     },
     {
@@ -134,7 +134,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Client 100.64.3.2 Port: 4500 - STUN client translation not found.",
+                "Client 100.64.3.2 Port: 4500 - STUN client translation not found",
                 "Client 172.18.3.2 Port: 4500 - Incorrect public-facing address - Expected: 192.118.3.2 Actual: 192.18.3.2",
                 "Client 172.18.3.2 Port: 4500 - Incorrect public-facing port - Expected: 6006 Actual: 4800",
             ],
@@ -163,7 +163,7 @@ DATA: list[dict[str, Any]] = [
         "expected": {
             "result": "failure",
             "messages": [
-                "Client 100.64.3.2 Port: 4500 - STUN client translation not found.",
+                "Client 100.64.3.2 Port: 4500 - STUN client translation not found",
                 "Client 172.18.4.2 Port: 4800 - Incorrect public-facing address - Expected: 192.118.3.2 Actual: 192.18.3.2",
                 "Client 172.18.4.2 Port: 4800 - Incorrect public-facing port - Expected: 6006 Actual: 4800",
             ],
@@ -193,7 +193,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": {},
         "expected": {
             "result": "failure",
-            "messages": ["STUN server status is disabled."],
+            "messages": ["STUN server status is disabled"],
         },
     },
     {
@@ -208,7 +208,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": {},
         "expected": {
             "result": "failure",
-            "messages": ["STUN server is not running."],
+            "messages": ["STUN server is not running"],
         },
     },
     {
@@ -223,7 +223,7 @@ DATA: list[dict[str, Any]] = [
         "inputs": {},
         "expected": {
             "result": "failure",
-            "messages": ["STUN server status is disabled and not running."],
+            "messages": ["STUN server status is disabled and not running"],
         },
     },
 ]
diff --git a/tests/units/anta_tests/test_system.py b/tests/units/anta_tests/test_system.py
index 403dd007..eb7c584f 100644
--- a/tests/units/anta_tests/test_system.py
+++ b/tests/units/anta_tests/test_system.py
@@ -34,7 +34,7 @@ DATA: list[dict[str, Any]] = [
         "test": VerifyUptime,
         "eos_data": [{"upTime": 665.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
         "inputs": {"minimum": 666},
-        "expected": {"result": "failure", "messages": ["Device uptime is incorrect - Expected: 666 Actual: 665.15 seconds"]},
+        "expected": {"result": "failure", "messages": ["Device uptime is incorrect - Expected: 666s Actual: 665.15s"]},
     },
     {
         "name": "success-no-reload",
diff --git a/tests/units/anta_tests/test_vlan.py b/tests/units/anta_tests/test_vlan.py
index 7fc8b868..fd900ca4 100644
--- a/tests/units/anta_tests/test_vlan.py
+++ b/tests/units/anta_tests/test_vlan.py
@@ -23,13 +23,21 @@ DATA: list[dict[str, Any]] = [
         "test": VerifyVlanInternalPolicy,
         "eos_data": [{"policy": "descending", "startVlanId": 4094, "endVlanId": 1006}],
         "inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
+        "expected": {
+            "result": "failure",
+            "messages": ["Incorrect VLAN internal allocation policy configured - Expected: ascending Actual: descending"],
+        },
+    },
+    {
+        "name": "failure-incorrect-start-end-id",
+        "test": VerifyVlanInternalPolicy,
+        "eos_data": [{"policy": "ascending", "startVlanId": 4094, "endVlanId": 1006}],
+        "inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
         "expected": {
             "result": "failure",
             "messages": [
-                "The VLAN internal allocation policy is not configured properly:\n"
-                "Expected `ascending` as the policy, but found `descending` instead.\n"
-                "Expected `1006` as the startVlanId, but found `4094` instead.\n"
-                "Expected `4094` as the endVlanId, but found `1006` instead."
+                "VLAN internal allocation policy: ascending - Incorrect start VLAN id configured - Expected: 1006 Actual: 4094",
+                "VLAN internal allocation policy: ascending - Incorrect end VLAN id configured - Expected: 4094 Actual: 1006",
             ],
         },
     },
diff --git a/tests/units/input_models/routing/test_bgp.py b/tests/units/input_models/routing/test_bgp.py
index 0ff859ff..d0ad243c 100644
--- a/tests/units/input_models/routing/test_bgp.py
+++ b/tests/units/input_models/routing/test_bgp.py
@@ -19,6 +19,7 @@ from anta.tests.routing.bgp import (
     VerifyBGPPeerGroup,
     VerifyBGPPeerMPCaps,
     VerifyBGPPeerRouteLimit,
+    VerifyBGPPeerTtlMultiHops,
     VerifyBGPRouteECMP,
     VerifyBgpRouteMaps,
     VerifyBGPRoutePaths,
@@ -435,3 +436,29 @@ class TestVerifyBGPAddressFamilyConfig:
     def test_valid_str(self, afi_safi: RedistributedAfiSafi, redistributed_routes: list[Any], expected: str) -> None:
         """Test AddressFamilyConfig __str__."""
         assert str(AddressFamilyConfig(afi_safi=afi_safi, redistributed_routes=redistributed_routes)) == expected
+
+
+class TestVerifyBGPPeerTtlMultiHopsInput:
+    """Test anta.tests.routing.bgp.VerifyBGPPeerTtlMultiHops.Input."""
+
+    @pytest.mark.parametrize(
+        ("bgp_peers"),
+        [
+            pytest.param([{"peer_address": "172.30.255.5", "vrf": "default", "ttl": 3, "max_ttl_hops": 3}], id="valid"),
+        ],
+    )
+    def test_valid(self, bgp_peers: list[BgpPeer]) -> None:
+        """Test VerifyBGPPeerTtlMultiHops.Input valid inputs."""
+        VerifyBGPPeerTtlMultiHops.Input(bgp_peers=bgp_peers)
+
+    @pytest.mark.parametrize(
+        ("bgp_peers"),
+        [
+            pytest.param([{"peer_address": "172.30.255.5", "vrf": "default", "ttl": None, "max_ttl_hops": 3}], id="invalid-ttl-time"),
+            pytest.param([{"peer_address": "172.30.255.6", "vrf": "default", "ttl": 3, "max_ttl_hops": None}], id="invalid-max-ttl-hops"),
+        ],
+    )
+    def test_invalid(self, bgp_peers: list[BgpPeer]) -> None:
+        """Test VerifyBGPPeerTtlMultiHops.Input invalid inputs."""
+        with pytest.raises(ValidationError):
+            VerifyBGPPeerTtlMultiHops.Input(bgp_peers=bgp_peers)
diff --git a/tests/units/inventory/test__init__.py b/tests/units/inventory/test__init__.py
index 9eee8803..461f0379 100644
--- a/tests/units/inventory/test__init__.py
+++ b/tests/units/inventory/test__init__.py
@@ -5,7 +5,7 @@
 
 from __future__ import annotations
 
-from pathlib import Path
+import logging
 from typing import TYPE_CHECKING
 
 import pytest
@@ -15,10 +15,9 @@ from anta.inventory import AntaInventory
 from anta.inventory.exceptions import InventoryIncorrectSchemaError, InventoryRootKeyError
 
 if TYPE_CHECKING:
-    from _pytest.mark.structures import ParameterSet
-
-FILE_DIR: Path = Path(__file__).parent.parent.resolve() / "data" / "inventory"
+    from pathlib import Path
 
+    from _pytest.mark.structures import ParameterSet
 
 INIT_VALID_PARAMS: list[ParameterSet] = [
     pytest.param(
@@ -76,3 +75,15 @@ class TestAntaInventory:
         """Parse invalid YAML file to create ANTA inventory."""
         with pytest.raises((InventoryIncorrectSchemaError, InventoryRootKeyError, ValidationError)):
             AntaInventory.parse(filename=yaml_file, username="arista", password="arista123")
+
+    def test_parse_wrong_format(self) -> None:
+        """Use wrong file format to parse the ANTA inventory."""
+        with pytest.raises(ValueError, match=" is not a valid format for an AntaInventory file. Only 'yaml' and 'json' are supported."):
+            AntaInventory.parse(filename="dummy.yml", username="arista", password="arista123", file_format="wrong")  # type: ignore[arg-type]
+
+    def test_parse_os_error(self, caplog: pytest.LogCaptureFixture) -> None:
+        """Use wrong file name to parse the ANTA inventory."""
+        caplog.set_level(logging.INFO)
+        with pytest.raises(OSError, match="No such file or directory"):
+            _ = AntaInventory.parse(filename="dummy.yml", username="arista", password="arista123")
+        assert "Unable to parse ANTA Device Inventory file" in caplog.records[0].message
diff --git a/tests/units/inventory/test_models.py b/tests/units/inventory/test_models.py
index 63ce7a78..f6bd7d63 100644
--- a/tests/units/inventory/test_models.py
+++ b/tests/units/inventory/test_models.py
@@ -5,16 +5,21 @@
 
 from __future__ import annotations
 
+import json
+from pathlib import Path
 from typing import TYPE_CHECKING, Any
 
 import pytest
 from pydantic import ValidationError
+from yaml import safe_load
 
-from anta.inventory.models import AntaInventoryHost, AntaInventoryNetwork, AntaInventoryRange
+from anta.inventory.models import AntaInventoryHost, AntaInventoryInput, AntaInventoryNetwork, AntaInventoryRange
 
 if TYPE_CHECKING:
     from _pytest.mark.structures import ParameterSet
 
+FILE_DIR: Path = Path(__file__).parents[2] / "data"
+
 INVENTORY_HOST_VALID_PARAMS: list[ParameterSet] = [
     pytest.param(None, "1.1.1.1", None, None, None, id="IPv4"),
     pytest.param(None, "fe80::cc62:a9ff:feef:932a", None, None, None, id="IPv6"),
@@ -164,3 +169,33 @@ class TestAntaInventoryRange:
         """Invalid model parameters."""
         with pytest.raises(ValidationError):
             AntaInventoryRange.model_validate({"start": start, "end": end, "tags": tags, "disable_cache": disable_cache})
+
+
+class TestAntaInventoryInputs:
+    """Test anta.inventory.models.AntaInventoryInputs."""
+
+    def test_dump_to_json(self) -> None:
+        """Load a YAML file, dump it to JSON and verify it works."""
+        input_yml_path = FILE_DIR / "test_inventory_with_tags.yml"
+        expected_json_path = FILE_DIR / "test_inventory_with_tags.json"
+        with input_yml_path.open("r") as f:
+            data = safe_load(f)
+        anta_inventory_input = AntaInventoryInput(**data["anta_inventory"])
+
+        with expected_json_path.open("r") as f:
+            expected_data = json.load(f)
+
+        assert anta_inventory_input.to_json() == json.dumps(expected_data["anta_inventory"], indent=2)
+
+    def test_dump_to_yaml(self) -> None:
+        """Load a JSON file, dump it to YAML and verify it works."""
+        input_json_path = FILE_DIR / "test_inventory_medium.json"
+        expected_yml_path = FILE_DIR / "test_inventory_medium.yml"
+        with input_json_path.open("r") as f:
+            data = json.load(f)
+        anta_inventory_input = AntaInventoryInput(**data["anta_inventory"])
+
+        with expected_yml_path.open("r") as f:
+            expected_data = safe_load(f)
+
+        assert safe_load(anta_inventory_input.yaml()) == expected_data["anta_inventory"]