Repository: dbt-labs/dbt-core

Issue:
[Bug] "FoundStats" message has incorrect node name plurals
### Is this a new bug in dbt-core?

- [X] I believe this is a new bug in dbt-core
- [X] I have searched the existing issues, and I could not find an existing issue for this bug

### Current Behavior

```
12:30:00  Found ... models, ... snapshots, ... analysiss, ...
```

### Expected Behavior

```
12:30:00  Found ... models, ... snapshots, ... analyses, ...
```

### Steps To Reproduce

1. Define a project with >1 analyses
2. Compile the project

### Relevant log output

_No response_

### Environment

```markdown
- OS: 13.4.1
- Python: 3.10.11
- dbt: main
```


### Which database adapter are you using with dbt?

_No response_

### Additional Context

We moved the `pluralize` logic into [dbt-common](https://github.com/dbt-labs/dbt-common/blob/6878a90c2ef313e8e183c315b58f9e6efdfabe0d/dbt_common/events/format.py#L38-L49).

If we're passing an object into `pluralize`, and it has its own `pluralize` method, we'll use it. If we're just passing a string, we won't.


Discussion:

Resolving patch:
diff --git a/core/dbt/artifacts/resources/types.py b/core/dbt/artifacts/resources/types.py
--- a/core/dbt/artifacts/resources/types.py
+++ b/core/dbt/artifacts/resources/types.py
@@ -18,7 +18,7 @@ def is_valid(cls, item):
 class NodeType(StrEnum):
     Model = "model"
     Analysis = "analysis"
-    Test = "test"
+    Test = "test"  # renamed to 'data_test'; preserved as 'test' here for back-compat
     Snapshot = "snapshot"
     Operation = "operation"
     Seed = "seed"
@@ -41,6 +41,8 @@ def pluralize(self) -> str:
             return "analyses"
         elif self is self.SavedQuery:
             return "saved_queries"
+        elif self is self.Test:
+            return "data_tests"
         return f"{self}s"
 
 
diff --git a/core/dbt/compilation.py b/core/dbt/compilation.py
--- a/core/dbt/compilation.py
+++ b/core/dbt/compilation.py
@@ -45,34 +45,14 @@
 graph_file_name = "graph.gpickle"
 
 
-def print_compile_stats(stats):
-    names = {
-        NodeType.Model: "model",
-        NodeType.Test: "data test",
-        NodeType.Unit: "unit test",
-        NodeType.Snapshot: "snapshot",
-        NodeType.Analysis: "analysis",
-        NodeType.Macro: "macro",
-        NodeType.Operation: "operation",
-        NodeType.Seed: "seed",
-        NodeType.Source: "source",
-        NodeType.Exposure: "exposure",
-        NodeType.SemanticModel: "semantic model",
-        NodeType.Metric: "metric",
-        NodeType.Group: "group",
-    }
-
-    results = {k: 0 for k in names.keys()}
-    results.update(stats)
-
+def print_compile_stats(stats: Dict[NodeType, int]):
     # create tracking event for resource_counts
     if dbt.tracking.active_user is not None:
-        resource_counts = {k.pluralize(): v for k, v in results.items()}
+        resource_counts = {k.pluralize(): v for k, v in stats.items()}
         dbt.tracking.track_resource_counts(resource_counts)
 
     # do not include resource types that are not actually defined in the project
-    stat_line = ", ".join([pluralize(ct, names.get(t)) for t, ct in stats.items() if t in names])
-
+    stat_line = ", ".join([pluralize(ct, t) for t, ct in stats.items() if ct != 0])
     fire_event(FoundStats(stat_line=stat_line))
 
 
@@ -84,7 +64,7 @@ def _node_enabled(node: ManifestNode):
         return True
 
 
-def _generate_stats(manifest: Manifest):
+def _generate_stats(manifest: Manifest) -> Dict[NodeType, int]:
     stats: Dict[NodeType, int] = defaultdict(int)
     for node in manifest.nodes.values():
         if _node_enabled(node):


Test patch:
diff --git a/tests/functional/minimal_cli/test_minimal_cli.py b/tests/functional/minimal_cli/test_minimal_cli.py
--- a/tests/functional/minimal_cli/test_minimal_cli.py
+++ b/tests/functional/minimal_cli/test_minimal_cli.py
@@ -35,7 +35,7 @@ def test_ls(self, runner, project):
         ls_result = runner.invoke(cli, ["ls"])
         assert "1 seed" in ls_result.output
         assert "1 model" in ls_result.output
-        assert "5 data tests" in ls_result.output
+        assert "5 data_tests" in ls_result.output
         assert "1 snapshot" in ls_result.output
 
 
diff --git a/tests/functional/schema_tests/test_schema_v2_tests.py b/tests/functional/schema_tests/test_schema_v2_tests.py
--- a/tests/functional/schema_tests/test_schema_v2_tests.py
+++ b/tests/functional/schema_tests/test_schema_v2_tests.py
@@ -906,7 +906,7 @@ def test_generic_test_collision(
         """These tests collide, since only the configs differ"""
         with pytest.raises(DuplicateResourceNameError) as exc:
             run_dbt()
-        assert "dbt found two tests with the name" in str(exc.value)
+        assert "dbt found two data_tests with the name" in str(exc.value)
 
 
 class TestGenericTestsConfigCustomMacros:
diff --git a/tests/unit/test_node_types.py b/tests/unit/test_node_types.py
--- a/tests/unit/test_node_types.py
+++ b/tests/unit/test_node_types.py
@@ -4,7 +4,7 @@
 node_type_pluralizations = {
     NodeType.Model: "models",
     NodeType.Analysis: "analyses",
-    NodeType.Test: "tests",
+    NodeType.Test: "data_tests",
     NodeType.Snapshot: "snapshots",
     NodeType.Operation: "operations",
     NodeType.Seed: "seeds",