diff --git a/poetry.lock b/poetry.lock
index d7470c271ca..226072a779a 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1161,12 +1161,16 @@ name = "poetry-core"
 version = "2.1.3"
 description = "Poetry PEP 517 Build Backend"
 optional = false
-python-versions = "<4.0,>=3.9"
+python-versions = ">=3.9, <4.0"
 groups = ["main"]
-files = [
-    {file = "poetry_core-2.1.3-py3-none-any.whl", hash = "sha256:2c704f05016698a54ca1d327f46ce2426d72eaca6ff614132c8477c292266771"},
-    {file = "poetry_core-2.1.3.tar.gz", hash = "sha256:0522a015477ed622c89aad56a477a57813cace0c8e7ff2a2906b7ef4a2e296a4"},
-]
+files = []
+develop = false
+
+[package.source]
+type = "git"
+url = "https://github.com/python-poetry/poetry-core.git"
+reference = "HEAD"
+resolved_reference = "12f0e00b34f97461709d8d65f9c5ec12d6f71da8"
 
 [[package]]
 name = "pre-commit"
@@ -1990,4 +1994,4 @@ cffi = ["cffi (>=1.11)"]
 [metadata]
 lock-version = "2.1"
 python-versions = ">=3.9,<4.0"
-content-hash = "f2793aa20e4a10c4d908f759fb731f32a563497fe0799ba44ef431ff8679dce8"
+content-hash = "0e8181aa29e95d0c347dd3536f5cff519d5b4f0431f4f9ab421f52015e117c75"
diff --git a/pyproject.toml b/pyproject.toml
index 97c82eb9956..6012f62b3d8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ version = "2.1.3"
 description = "Python dependency management and packaging made easy."
 requires-python = ">=3.9,<4.0"
 dependencies = [
-    "poetry-core (==2.1.3)",
+    "poetry-core @ git+https://github.com/python-poetry/poetry-core.git",
     "build (>=1.2.1,<2.0.0)",
     "cachecontrol[filecache] (>=0.14.0,<0.15.0)",
     "cleo (>=2.1.0,<3.0.0)",
diff --git a/src/poetry/console/commands/group_command.py b/src/poetry/console/commands/group_command.py
index 06dea92cc78..d876884fe55 100644
--- a/src/poetry/console/commands/group_command.py
+++ b/src/poetry/console/commands/group_command.py
@@ -4,6 +4,8 @@
 from typing import TYPE_CHECKING
 
 from cleo.helpers import option
+from packaging.utils import NormalizedName
+from packaging.utils import canonicalize_name
 
 from poetry.console.commands.command import Command
 from poetry.console.exceptions import GroupNotFoundError
@@ -70,7 +72,7 @@ def default_groups(self) -> set[str]:
         return self.non_optional_groups
 
     @property
-    def activated_groups(self) -> set[str]:
+    def activated_groups(self) -> set[NormalizedName]:
         groups = {}
 
         for key in {"with", "without", "only"}:
@@ -95,9 +97,17 @@ def activated_groups(self) -> set[str]:
                 "</warning>"
             )
 
-        return groups["only"] or self.default_groups.union(groups["with"]).difference(
-            groups["without"]
-        )
+        # Normalize after validating so that original names are printed
+        # in case of an error.
+        norm_groups = {
+            key: {canonicalize_name(group) for group in key_groups}
+            for key, key_groups in groups.items()
+        }
+        norm_default_groups = {canonicalize_name(name) for name in self.default_groups}
+
+        return norm_groups["only"] or norm_default_groups.union(
+            norm_groups["with"]
+        ).difference(norm_groups["without"])
 
     def project_with_activated_groups_only(self) -> ProjectPackage:
         return self.poetry.package.with_dependency_groups(
diff --git a/src/poetry/console/commands/install.py b/src/poetry/console/commands/install.py
index b797c24ada8..4e31d9d1a78 100644
--- a/src/poetry/console/commands/install.py
+++ b/src/poetry/console/commands/install.py
@@ -11,6 +11,7 @@
 
 if TYPE_CHECKING:
     from cleo.io.inputs.option import Option
+    from packaging.utils import NormalizedName
 
 
 class InstallCommand(InstallerCommand):
@@ -83,7 +84,7 @@ class InstallCommand(InstallerCommand):
     ]
 
     @property
-    def activated_groups(self) -> set[str]:
+    def activated_groups(self) -> set[NormalizedName]:
         if self.option("only-root"):
             return set()
         else:
diff --git a/src/poetry/console/commands/self/install.py b/src/poetry/console/commands/self/install.py
index 6f0399b2ae2..b4c9a1e2644 100644
--- a/src/poetry/console/commands/self/install.py
+++ b/src/poetry/console/commands/self/install.py
@@ -3,6 +3,8 @@
 from typing import TYPE_CHECKING
 from typing import ClassVar
 
+from packaging.utils import NormalizedName
+from packaging.utils import canonicalize_name
 from poetry.core.packages.dependency_group import MAIN_GROUP
 
 from poetry.console.commands.install import InstallCommand
@@ -33,8 +35,8 @@ class SelfInstallCommand(SelfCommand, InstallCommand):
 """
 
     @property
-    def activated_groups(self) -> set[str]:
-        return {MAIN_GROUP, self.default_group}
+    def activated_groups(self) -> set[NormalizedName]:
+        return {MAIN_GROUP, canonicalize_name(self.default_group)}
 
     @property
     def _alternative_sync_command(self) -> str:
diff --git a/src/poetry/console/commands/self/self_command.py b/src/poetry/console/commands/self/self_command.py
index 6b049d3b459..316fd3ec5f9 100644
--- a/src/poetry/console/commands/self/self_command.py
+++ b/src/poetry/console/commands/self/self_command.py
@@ -3,6 +3,7 @@
 from pathlib import Path
 from typing import TYPE_CHECKING
 
+from packaging.utils import canonicalize_name
 from poetry.core.packages.dependency import Dependency
 from poetry.core.packages.project_package import ProjectPackage
 
@@ -16,12 +17,14 @@
 
 
 if TYPE_CHECKING:
+    from packaging.utils import NormalizedName
+
     from poetry.poetry import Poetry
     from poetry.utils.env import Env
 
 
 class SelfCommand(InstallerCommand):
-    ADDITIONAL_PACKAGE_GROUP = "additional"
+    ADDITIONAL_PACKAGE_GROUP = canonicalize_name("additional")
 
     @staticmethod
     def get_default_system_pyproject_file() -> Path:
@@ -54,8 +57,8 @@ def default_group(self) -> str:
         return self.ADDITIONAL_PACKAGE_GROUP
 
     @property
-    def activated_groups(self) -> set[str]:
-        return {self.default_group}
+    def activated_groups(self) -> set[NormalizedName]:
+        return {canonicalize_name(self.default_group)}
 
     def generate_system_pyproject(self) -> None:
         preserved = {}
diff --git a/src/poetry/console/commands/self/show/__init__.py b/src/poetry/console/commands/self/show/__init__.py
index 8f4060ad2a3..e0e5fcc32cb 100644
--- a/src/poetry/console/commands/self/show/__init__.py
+++ b/src/poetry/console/commands/self/show/__init__.py
@@ -11,6 +11,7 @@
 
 if TYPE_CHECKING:
     from cleo.io.inputs.option import Option
+    from packaging.utils import NormalizedName
 
 
 class SelfShowCommand(SelfCommand, ShowCommand):
@@ -33,9 +34,8 @@ class SelfShowCommand(SelfCommand, ShowCommand):
 """
 
     @property
-    def activated_groups(self) -> set[str]:
+    def activated_groups(self) -> set[NormalizedName]:
         if self.option("addons", False):
             return {SelfCommand.ADDITIONAL_PACKAGE_GROUP}
 
-        groups: set[str] = super(ShowCommand, self).activated_groups
-        return groups
+        return super(ShowCommand, self).activated_groups
diff --git a/src/poetry/installation/installer.py b/src/poetry/installation/installer.py
index e86fb540a0a..b4e9eaaaafd 100644
--- a/src/poetry/installation/installer.py
+++ b/src/poetry/installation/installer.py
@@ -54,7 +54,7 @@ def __init__(
         self._requires_synchronization = False
         self._update = False
         self._verbose = False
-        self._groups: Iterable[str] | None = None
+        self._groups: Iterable[NormalizedName] | None = None
         self._skip_directory = False
         self._lock = False
 
@@ -127,7 +127,7 @@ def verbose(self, verbose: bool = True) -> Installer:
     def is_verbose(self) -> bool:
         return self._verbose
 
-    def only_groups(self, groups: Iterable[str]) -> Installer:
+    def only_groups(self, groups: Iterable[NormalizedName]) -> Installer:
         self._groups = groups
 
         return self
diff --git a/src/poetry/packages/locker.py b/src/poetry/packages/locker.py
index 20645c7fec6..ff23bc2918c 100644
--- a/src/poetry/packages/locker.py
+++ b/src/poetry/packages/locker.py
@@ -162,13 +162,20 @@ def locked_packages(self) -> dict[Package, TransitivePackageInfo]:
             groups = set(info["groups"])
             locked_marker = info.get("markers", "*")
             if isinstance(locked_marker, str):
-                markers = {group: parse_marker(locked_marker) for group in groups}
+                markers = {
+                    canonicalize_name(group): parse_marker(locked_marker)
+                    for group in groups
+                }
             else:
                 markers = {
-                    group: parse_marker(locked_marker.get(group, "*"))
+                    canonicalize_name(group): parse_marker(
+                        locked_marker.get(group, "*")
+                    )
                     for group in groups
                 }
-            locked_packages[package] = TransitivePackageInfo(0, groups, markers)
+            locked_packages[package] = TransitivePackageInfo(
+                0, {canonicalize_name(g) for g in groups}, markers
+            )
 
         return locked_packages
 
@@ -553,23 +560,23 @@ def _dump_package(
                     data["markers"] = str(marker)
             else:
                 data["markers"] = inline_table()
-                for k, v in sorted(
+                for group, marker in sorted(
                     transitive_info.markers.items(),
                     key=lambda x: (x[0] != "main", x[0]),
                 ):
-                    if not v.is_any():
-                        data["markers"][k] = str(v)
+                    if not marker.is_any():
+                        data["markers"][group] = str(marker)
         data["files"] = sorted(package.files, key=lambda x: x["file"])
 
         if dependencies:
             data["dependencies"] = table()
-            for k, constraints in dependencies.items():
+            for dep_name, constraints in dependencies.items():
                 if len(constraints) == 1:
-                    data["dependencies"][k] = constraints[0]
+                    data["dependencies"][dep_name] = constraints[0]
                 else:
-                    data["dependencies"][k] = array().multiline(True)
+                    data["dependencies"][dep_name] = array().multiline(True)
                     for constraint in constraints:
-                        data["dependencies"][k].append(constraint)
+                        data["dependencies"][dep_name].append(constraint)
 
         if package.extras:
             extras = {}
diff --git a/src/poetry/packages/transitive_package_info.py b/src/poetry/packages/transitive_package_info.py
index 82960ec08d3..89c28a25a45 100644
--- a/src/poetry/packages/transitive_package_info.py
+++ b/src/poetry/packages/transitive_package_info.py
@@ -10,14 +10,16 @@
 if TYPE_CHECKING:
     from collections.abc import Iterable
 
+    from packaging.utils import NormalizedName
+
 
 @dataclass
 class TransitivePackageInfo:
     depth: int  # max depth in the dependency tree
-    groups: set[str]
-    markers: dict[str, BaseMarker]  # group -> marker
+    groups: set[NormalizedName]
+    markers: dict[NormalizedName, BaseMarker]  # group -> marker
 
-    def get_marker(self, groups: Iterable[str]) -> BaseMarker:
+    def get_marker(self, groups: Iterable[NormalizedName]) -> BaseMarker:
         marker: BaseMarker = EmptyMarker()
         for group in groups:
             if group_marker := self.markers.get(group):
diff --git a/src/poetry/puzzle/solver.py b/src/poetry/puzzle/solver.py
index b2b4912d30b..26810cc2aeb 100644
--- a/src/poetry/puzzle/solver.py
+++ b/src/poetry/puzzle/solver.py
@@ -299,7 +299,7 @@ def __init__(
         self.depth = -1
 
         if not previous:
-            self.groups: frozenset[str] = frozenset()
+            self.groups: frozenset[NormalizedName] = frozenset()
             self.optional = True
         elif dep:
             self.groups = dep.groups
@@ -361,7 +361,7 @@ def aggregate_package_nodes(
 ) -> tuple[Package, TransitivePackageInfo]:
     package = nodes[0].package
     depth = max(node.depth for node in nodes)
-    groups: set[str] = set()
+    groups: set[NormalizedName] = set()
     for node in nodes:
         groups.update(node.groups)
 
@@ -395,7 +395,7 @@ def calculate_markers(
         for depth in range(max_depth + 1):
             for package in packages_by_depth[depth]:
                 transitive_info = packages[package]
-                transitive_marker: dict[str, BaseMarker] = {
+                transitive_marker: dict[NormalizedName, BaseMarker] = {
                     group: EmptyMarker() for group in transitive_info.groups
                 }
                 for parent, m in markers[package].items():
diff --git a/src/poetry/puzzle/transaction.py b/src/poetry/puzzle/transaction.py
index 3c76bda3876..ecd78fc2457 100644
--- a/src/poetry/puzzle/transaction.py
+++ b/src/poetry/puzzle/transaction.py
@@ -23,7 +23,7 @@ def __init__(
         installed_packages: list[Package] | None = None,
         root_package: Package | None = None,
         marker_env: dict[str, Any] | None = None,
-        groups: set[str] | None = None,
+        groups: set[NormalizedName] | None = None,
     ) -> None:
         self._current_packages = current_packages
         self._result_packages = result_packages
diff --git a/tests/installation/test_installer.py b/tests/installation/test_installer.py
index c4560f31907..851c9594b80 100644
--- a/tests/installation/test_installer.py
+++ b/tests/installation/test_installer.py
@@ -437,7 +437,7 @@ def test_run_install_with_dependency_groups(
     )
 
     if groups is not None:
-        installer.only_groups(groups)
+        installer.only_groups({canonicalize_name(g) for g in groups})
 
     installer.update(update)
     installer.requires_synchronization(requires_synchronization)
diff --git a/tests/packages/test_locker.py b/tests/packages/test_locker.py
index 7dce9bfeebf..8fa05d9f672 100644
--- a/tests/packages/test_locker.py
+++ b/tests/packages/test_locker.py
@@ -35,6 +35,9 @@
     from pytest_mock import MockerFixture
 
 
+DEV_GROUP = canonicalize_name("dev")
+
+
 @pytest.fixture
 def locker() -> Locker:
     with tempfile.NamedTemporaryFile() as f:
@@ -466,17 +469,21 @@ def test_locker_properly_loads_subdir(locker: Locker) -> None:
 @pytest.mark.parametrize(
     ("groups", "marker", "expected"),
     [
+        # only main - without marker
         (["main"], None, {"main": "*"}),
+        # only main - with marker
         (
             ["main"],
             repr('python_version == "3.9"'),
             {"main": 'python_version == "3.9"'},
         ),
+        # two groups - common marker
         (
             ["main", "dev"],
             repr('python_version == "3.9"'),
             {"main": 'python_version == "3.9"', "dev": 'python_version == "3.9"'},
         ),
+        # two groups - separate marker
         (
             ["main", "dev"],
             (
@@ -485,11 +492,27 @@ def test_locker_properly_loads_subdir(locker: Locker) -> None:
             ),
             {"main": 'python_version == "3.9"', "dev": 'sys_platform == "linux"'},
         ),
+        # two groups - one without marker
         (
             ["main", "dev"],
             '{"main" = \'python_version == "3.9"\'}',
             {"main": 'python_version == "3.9"', "dev": "*"},
         ),
+        (
+            # unnormalized group - common marker
+            ["main", "DEV"],
+            repr('python_version == "3.9"'),
+            {"main": 'python_version == "3.9"', "dev": 'python_version == "3.9"'},
+        ),
+        (
+            # unnormalized group - separate marker
+            ["main", "DEV"],
+            (
+                '{"main" = \'python_version == "3.9"\','
+                ' "DEV" = \'sys_platform == "linux"\'}'
+            ),
+            {"main": 'python_version == "3.9"', "dev": 'sys_platform == "linux"'},
+        ),
     ],
 )
 def test_locker_properly_loads_groups_and_markers(
@@ -517,7 +540,7 @@ def test_locker_properly_loads_groups_and_markers(
 
     a = get_package("a", "1.0")
     assert len(packages) == 1
-    assert packages[a].groups == set(groups)
+    assert packages[a].groups == {canonicalize_name(g) for g in groups}
     assert packages[a].markers == {g: parse_marker(m) for g, m in expected.items()}
 
 
@@ -997,36 +1020,38 @@ def test_locker_dumps_groups_and_markers(
 ) -> None:
     packages = {
         get_package("A", "1.0"): TransitivePackageInfo(
-            0, {"main"}, {"main": AnyMarker()}
+            0, {MAIN_GROUP}, {MAIN_GROUP: AnyMarker()}
         ),
         get_package("B", "1.0"): TransitivePackageInfo(
-            0, {"main"}, {"main": parse_marker('sys_platform == "win32"')}
+            0, {MAIN_GROUP}, {MAIN_GROUP: parse_marker('sys_platform == "win32"')}
         ),
         get_package("C", "1.0"): TransitivePackageInfo(
-            0, {"main", "dev"}, {"main": AnyMarker(), "dev": AnyMarker()}
+            0,
+            {MAIN_GROUP, DEV_GROUP},
+            {MAIN_GROUP: AnyMarker(), DEV_GROUP: AnyMarker()},
         ),
         get_package("D", "1.0"): TransitivePackageInfo(
             0,
-            {"main", "dev"},
+            {MAIN_GROUP, DEV_GROUP},
             {
-                "main": parse_marker('sys_platform == "win32"'),
-                "dev": parse_marker('sys_platform == "win32"'),
+                MAIN_GROUP: parse_marker('sys_platform == "win32"'),
+                DEV_GROUP: parse_marker('sys_platform == "win32"'),
             },
         ),
         get_package("E", "1.0"): TransitivePackageInfo(
             0,
-            {"main", "dev"},
+            {MAIN_GROUP, DEV_GROUP},
             {
-                "main": parse_marker('sys_platform == "win32"'),
-                "dev": parse_marker('sys_platform == "linux"'),
+                MAIN_GROUP: parse_marker('sys_platform == "win32"'),
+                DEV_GROUP: parse_marker('sys_platform == "linux"'),
             },
         ),
         get_package("F", "1.0"): TransitivePackageInfo(
             0,
-            {"main", "dev"},
+            {MAIN_GROUP, DEV_GROUP},
             {
-                "main": parse_marker('sys_platform == "win32"'),
-                "dev": AnyMarker(),
+                MAIN_GROUP: parse_marker('sys_platform == "win32"'),
+                DEV_GROUP: AnyMarker(),
             },
         ),
     }
diff --git a/tests/packages/test_transitive_package_info.py b/tests/packages/test_transitive_package_info.py
index 8532555ba98..89809b65afa 100644
--- a/tests/packages/test_transitive_package_info.py
+++ b/tests/packages/test_transitive_package_info.py
@@ -2,11 +2,16 @@
 
 import pytest
 
+from packaging.utils import canonicalize_name
+from poetry.core.packages.dependency_group import MAIN_GROUP
 from poetry.core.version.markers import parse_marker
 
 from poetry.packages.transitive_package_info import TransitivePackageInfo
 
 
+DEV_GROUP = canonicalize_name("dev")
+
+
 @pytest.mark.parametrize(
     "groups, expected",
     [
@@ -21,10 +26,10 @@
 def test_get_marker(groups: list[str], expected: str) -> None:
     info = TransitivePackageInfo(
         depth=0,
-        groups={"main", "dev"},
+        groups={MAIN_GROUP, DEV_GROUP},
         markers={
-            "main": parse_marker('sys_platform =="linux"'),
-            "dev": parse_marker('python_version < "3.9"'),
+            MAIN_GROUP: parse_marker('sys_platform =="linux"'),
+            DEV_GROUP: parse_marker('python_version < "3.9"'),
         },
     )
-    assert str(info.get_marker(groups)) == expected
+    assert str(info.get_marker([canonicalize_name(g) for g in groups])) == expected
diff --git a/tests/puzzle/test_solver.py b/tests/puzzle/test_solver.py
index cc4f7708f7b..a13a1a2fd4a 100644
--- a/tests/puzzle/test_solver.py
+++ b/tests/puzzle/test_solver.py
@@ -5090,8 +5090,12 @@ def test_solver_resolves_conflicting_dependency_in_root_extra(
         ),
     )
     solved_packages = transaction.get_solved_packages()
-    assert solved_packages[package_a1].markers["main"] == parse_marker("extra != 'foo'")
-    assert solved_packages[package_a2].markers["main"] == parse_marker("extra == 'foo'")
+    assert solved_packages[package_a1].markers[MAIN_GROUP] == parse_marker(
+        "extra != 'foo'"
+    )
+    assert solved_packages[package_a2].markers[MAIN_GROUP] == parse_marker(
+        "extra == 'foo'"
+    )
 
 
 def test_solver_resolves_conflicting_dependency_in_root_extras(
@@ -5136,10 +5140,10 @@ def test_solver_resolves_conflicting_dependency_in_root_extras(
         ),
     )
     solved_packages = transaction.get_solved_packages()
-    assert solved_packages[package_a1].markers["main"] == parse_marker(
+    assert solved_packages[package_a1].markers[MAIN_GROUP] == parse_marker(
         "extra != 'bar' and extra == 'foo'"
     )
-    assert solved_packages[package_a2].markers["main"] == parse_marker(
+    assert solved_packages[package_a2].markers[MAIN_GROUP] == parse_marker(
         "extra != 'foo' and extra == 'bar'"
     )
 
diff --git a/tests/puzzle/test_solver_internals.py b/tests/puzzle/test_solver_internals.py
index 3ca8cdc21d6..807a9a32b62 100644
--- a/tests/puzzle/test_solver_internals.py
+++ b/tests/puzzle/test_solver_internals.py
@@ -7,6 +7,7 @@
 from packaging.utils import canonicalize_name
 from poetry.core.constraints.version import parse_constraint
 from poetry.core.packages.dependency import Dependency
+from poetry.core.packages.dependency_group import MAIN_GROUP
 from poetry.core.packages.package import Package
 from poetry.core.version.markers import AnyMarker
 from poetry.core.version.markers import parse_marker
@@ -26,6 +27,9 @@
     from poetry.core.packages.project_package import ProjectPackage
 
 
+DEV_GROUP = canonicalize_name("dev")
+
+
 def dep(
     name: str,
     marker: str = "",
@@ -369,7 +373,9 @@ def test_merge_override_packages_restricted(package: ProjectPackage) -> None:
                 {package: {"a": dep("b", 'python_version < "3.9"')}},
                 {
                     a: TransitivePackageInfo(
-                        0, {"main"}, {"main": parse_marker("sys_platform == 'win32'")}
+                        0,
+                        {MAIN_GROUP},
+                        {MAIN_GROUP: parse_marker("sys_platform == 'win32'")},
                     )
                 },
             ),
@@ -377,7 +383,9 @@ def test_merge_override_packages_restricted(package: ProjectPackage) -> None:
                 {package: {"a": dep("b", 'python_version >= "3.9"')}},
                 {
                     a: TransitivePackageInfo(
-                        0, {"main"}, {"main": parse_marker("sys_platform == 'linux'")}
+                        0,
+                        {MAIN_GROUP},
+                        {MAIN_GROUP: parse_marker("sys_platform == 'linux'")},
                     )
                 },
             ),
@@ -404,7 +412,9 @@ def test_merge_override_packages_extras(package: ProjectPackage) -> None:
                 {package: {"a": dep("b", 'python_version < "3.9" and extra == "foo"')}},
                 {
                     a: TransitivePackageInfo(
-                        0, {"main"}, {"main": parse_marker("sys_platform == 'win32'")}
+                        0,
+                        {MAIN_GROUP},
+                        {MAIN_GROUP: parse_marker("sys_platform == 'win32'")},
                     )
                 },
             ),
@@ -416,7 +426,9 @@ def test_merge_override_packages_extras(package: ProjectPackage) -> None:
                 },
                 {
                     a: TransitivePackageInfo(
-                        0, {"main"}, {"main": parse_marker("sys_platform == 'linux'")}
+                        0,
+                        {MAIN_GROUP},
+                        {MAIN_GROUP: parse_marker("sys_platform == 'linux'")},
                     )
                 },
             ),
@@ -456,11 +468,11 @@ def test_merge_override_packages_python_constraint(
                         )
                     }
                 },
-                {a: TransitivePackageInfo(0, {"main"}, {"main": AnyMarker()})},
+                {a: TransitivePackageInfo(0, {MAIN_GROUP}, {MAIN_GROUP: AnyMarker()})},
             ),
             (
                 {package: {"a": dep("b", "sys_platform != 'linux'")}},
-                {a: TransitivePackageInfo(0, {"main"}, {"main": AnyMarker()})},
+                {a: TransitivePackageInfo(0, {MAIN_GROUP}, {MAIN_GROUP: AnyMarker()})},
             ),
         ],
         parse_constraint(python_constraint),
@@ -484,7 +496,7 @@ def test_merge_override_packages_multiple_deps(package: ProjectPackage) -> None:
                     },
                     a: {"e": dep("f", 'python_version >= "3.8"')},
                 },
-                {a: TransitivePackageInfo(0, {"main"}, {"main": AnyMarker()})},
+                {a: TransitivePackageInfo(0, {MAIN_GROUP}, {MAIN_GROUP: AnyMarker()})},
             ),
         ],
         parse_constraint("*"),
@@ -507,14 +519,16 @@ def test_merge_override_packages_groups(package: ProjectPackage) -> None:
                 {package: {"a": dep("b", 'python_version < "3.9"')}},
                 {
                     a: TransitivePackageInfo(
-                        0, {"main"}, {"main": parse_marker("sys_platform == 'win32'")}
+                        0,
+                        {MAIN_GROUP},
+                        {MAIN_GROUP: parse_marker("sys_platform == 'win32'")},
                     ),
                     b: TransitivePackageInfo(
                         0,
-                        {"main", "dev"},
+                        {MAIN_GROUP, DEV_GROUP},
                         {
-                            "main": parse_marker("sys_platform == 'win32'"),
-                            "dev": parse_marker("sys_platform == 'linux'"),
+                            MAIN_GROUP: parse_marker("sys_platform == 'win32'"),
+                            DEV_GROUP: parse_marker("sys_platform == 'linux'"),
                         },
                     ),
                 },
@@ -523,14 +537,16 @@ def test_merge_override_packages_groups(package: ProjectPackage) -> None:
                 {package: {"a": dep("b", 'python_version >= "3.9"')}},
                 {
                     a: TransitivePackageInfo(
-                        0, {"dev"}, {"dev": parse_marker("sys_platform == 'linux'")}
+                        0,
+                        {DEV_GROUP},
+                        {DEV_GROUP: parse_marker("sys_platform == 'linux'")},
                     ),
                     b: TransitivePackageInfo(
                         0,
-                        {"main", "dev"},
+                        {MAIN_GROUP, DEV_GROUP},
                         {
-                            "main": parse_marker("platform_machine == 'amd64'"),
-                            "dev": parse_marker("platform_machine == 'aarch64'"),
+                            MAIN_GROUP: parse_marker("platform_machine == 'amd64'"),
+                            DEV_GROUP: parse_marker("platform_machine == 'aarch64'"),
                         },
                     ),
                 },
@@ -573,9 +589,9 @@ def test_merge_override_packages_shortcut(package: ProjectPackage) -> None:
                 {
                     a: TransitivePackageInfo(
                         0,
-                        {"main"},
+                        {MAIN_GROUP},
                         {
-                            "main": parse_marker(
+                            MAIN_GROUP: parse_marker(
                                 f"{override_marker1} and ({common_marker})"
                             )
                         },
@@ -587,9 +603,9 @@ def test_merge_override_packages_shortcut(package: ProjectPackage) -> None:
                 {
                     a: TransitivePackageInfo(
                         0,
-                        {"main"},
+                        {MAIN_GROUP},
                         {
-                            "main": parse_marker(
+                            MAIN_GROUP: parse_marker(
                                 f"{override_marker2} and ({common_marker})"
                             )
                         },
diff --git a/tests/puzzle/test_transaction.py b/tests/puzzle/test_transaction.py
index 1a31deb5369..3f940c6b7bf 100644
--- a/tests/puzzle/test_transaction.py
+++ b/tests/puzzle/test_transaction.py
@@ -7,6 +7,7 @@
 
 from packaging.utils import canonicalize_name
 from poetry.core.packages.dependency import Dependency
+from poetry.core.packages.dependency_group import MAIN_GROUP
 from poetry.core.packages.package import Package
 from poetry.core.packages.project_package import ProjectPackage
 from poetry.core.version.markers import AnyMarker
@@ -21,6 +22,9 @@
     from poetry.installation.operations.operation import Operation
 
 
+DEV_GROUP = canonicalize_name("dev")
+
+
 def get_transitive_info(depth: int) -> TransitivePackageInfo:
     return TransitivePackageInfo(depth, set(), {})
 
@@ -271,11 +275,15 @@ def test_calculate_operations_with_groups(
         [Package("a", "1"), Package("b", "1"), Package("c", "1"), Package("d", "1")],
         {
             Package("a", "1"): TransitivePackageInfo(
-                0, {"main"}, {"main": AnyMarker()}
+                0, {MAIN_GROUP}, {MAIN_GROUP: AnyMarker()}
+            ),
+            Package("b", "1"): TransitivePackageInfo(
+                0, {DEV_GROUP}, {DEV_GROUP: AnyMarker()}
             ),
-            Package("b", "1"): TransitivePackageInfo(0, {"dev"}, {"dev": AnyMarker()}),
             Package("c", "1"): TransitivePackageInfo(
-                0, {"main", "dev"}, {"main": AnyMarker(), "dev": AnyMarker()}
+                0,
+                {MAIN_GROUP, DEV_GROUP},
+                {MAIN_GROUP: AnyMarker(), DEV_GROUP: AnyMarker()},
             ),
         },
         (
@@ -285,7 +293,7 @@ def test_calculate_operations_with_groups(
         ),
         None,
         {"python_version": "3.8"},
-        groups,
+        {canonicalize_name(g) for g in groups},
     )
 
     expected_ops = [
@@ -322,16 +330,16 @@ def test_calculate_operations_with_markers(
         [Package("a", "1"), Package("b", "1")],
         {
             Package("a", "1"): TransitivePackageInfo(
-                0, {"main"}, {"main": parse_marker("python_version < '3.9'")}
+                0, {MAIN_GROUP}, {MAIN_GROUP: parse_marker("python_version < '3.9'")}
             ),
             Package("b", "1"): TransitivePackageInfo(
-                0, {"main"}, {"main": parse_marker("python_version >= '3.9'")}
+                0, {MAIN_GROUP}, {MAIN_GROUP: parse_marker("python_version >= '3.9'")}
             ),
         },
         [Package("a", "1"), Package("b", "1")] if installed else [],
         None,
         {"python_version": python_version},
-        {"main"},
+        {MAIN_GROUP},
     )
 
     expected_ops = [
@@ -374,17 +382,17 @@ def test_calculate_operations_with_groups_and_markers(
         {
             Package("a", "1"): TransitivePackageInfo(
                 0,
-                {"main", "dev"},
+                {MAIN_GROUP, DEV_GROUP},
                 {
-                    "main": parse_marker("python_version < '3.9'"),
-                    "dev": parse_marker("sys_platform == 'linux'"),
+                    MAIN_GROUP: parse_marker("python_version < '3.9'"),
+                    DEV_GROUP: parse_marker("sys_platform == 'linux'"),
                 },
             ),
         },
         [],
         None,
         {"python_version": python_version, "sys_platform": sys_platform},
-        groups,
+        {canonicalize_name(g) for g in groups},
     )
 
     expected_ops = (
@@ -420,14 +428,14 @@ def test_calculate_operations_extras(
         {
             opt_a: TransitivePackageInfo(
                 0,
-                {"main"} if marker_env else set(),
-                {"main": parse_marker("extra == 'foo'")} if marker_env else {},
+                {MAIN_GROUP} if marker_env else set(),
+                {MAIN_GROUP: parse_marker("extra == 'foo'")} if marker_env else {},
             )
         },
         [Package("a", "1")] if installed else [],
         package,
         {"python_version": "3.8"} if marker_env else None,
-        {"main"} if marker_env else None,
+        {MAIN_GROUP} if marker_env else None,
     )
 
     if extras:
@@ -473,16 +481,20 @@ def test_calculate_operations_extras_no_redundant_uninstall(extra: str) -> None:
         [Package("a", "1")],
         {
             opt_a1: TransitivePackageInfo(
-                0, {"main"}, {"main": parse_marker("extra == 'foo' and extra != 'bar'")}
+                0,
+                {MAIN_GROUP},
+                {MAIN_GROUP: parse_marker("extra == 'foo' and extra != 'bar'")},
             ),
             opt_a2: TransitivePackageInfo(
-                0, {"main"}, {"main": parse_marker("extra == 'bar' and extra != 'foo'")}
+                0,
+                {MAIN_GROUP},
+                {MAIN_GROUP: parse_marker("extra == 'bar' and extra != 'foo'")},
             ),
         },
         [Package("a", "1")],
         package,
         {"python_version": "3.9"},
-        {"main"},
+        {MAIN_GROUP},
     )
 
     if not extra:
