Repository: tox-dev/tox

Issue:
Can't suppress report via -qq
## Issue

With a command that outputs information to stdout, it's hard to use `tox` to execute that and capture the result since `tox` insists on printing a report afterwards.

e.g. 
```console
$ TERM=dumb tox exec -qq -- python -c 'print("foo")' | wc -l
```

expect `1`, get `3`

See `_print` in https://github.com/tox-dev/tox/blob/2df6015c053670eaf7b2aaa0ef48c96d140a0ba4/src/tox/session/cmd/run/common.py#L145-L166

## Environment

Provide at least:

- OS: Ubuntu 22.04 LTS
- `pip list` of the host Python where `tox` is installed: https://paste.ubuntu.com/p/BbbJ7bz8Hd/

## Output of running tox

Provide the output of `tox -rvv`:

https://paste.ubuntu.com/p/X85DB6HDw5/

## Minimal example

If possible, provide a minimal reproducer for the issue:

```console
git clone https://github.com/tox-dev/tox.git
env -C tox python3 -m tox exec -e dev -qq -- python -c 'print("foo")'
```


Discussion:

Patch:
diff --git a/docs/changelog/2697.feature.rst b/docs/changelog/2697.feature.rst
new file mode 100644
index 00000000..7ed95ea8
--- /dev/null
+++ b/docs/changelog/2697.feature.rst
@@ -0,0 +1,1 @@
+Suppress a report output when verbosity = 0.
diff --git a/src/tox/session/cmd/run/common.py b/src/tox/session/cmd/run/common.py
index e8a5eeb7..cc546e13 100644
--- a/src/tox/session/cmd/run/common.py
+++ b/src/tox/session/cmd/run/common.py
@@ -165,9 +165,10 @@ def env_run_create_flags(parser: ArgumentParser, mode: str) -> None:
         )
 
 
-def report(start: float, runs: list[ToxEnvRunResult], is_colored: bool) -> int:
+def report(start: float, runs: list[ToxEnvRunResult], is_colored: bool, verbosity: int) -> int:
     def _print(color_: int, message: str) -> None:
-        print(f"{color_ if is_colored else ''}{message}{Fore.RESET if is_colored else ''}")
+        if verbosity:
+            print(f"{color_ if is_colored else ''}{message}{Fore.RESET if is_colored else ''}")
 
     successful, skipped = [], []
     for run in runs:
@@ -250,7 +251,12 @@ def execute(state: State, max_workers: int | None, has_spinner: bool, live: bool
         # write the journal
         write_journal(getattr(state.conf.options, "result_json", None), state._journal)
         # report the outcome
-        exit_code = report(state.conf.options.start, ordered_results, state.conf.options.is_colored)
+        exit_code = report(
+            state.conf.options.start,
+            ordered_results,
+            state.conf.options.is_colored,
+            state.conf.options.verbosity,
+        )
         if has_previous:
             signal(SIGINT, previous)
     return exit_code


Test patch:
diff --git a/tests/session/cmd/run/test_common.py b/tests/session/cmd/run/test_common.py
index 5f8cf476..3a0866cc 100644
--- a/tests/session/cmd/run/test_common.py
+++ b/tests/session/cmd/run/test_common.py
@@ -1,11 +1,13 @@
 from __future__ import annotations
 
+import os
 import re
 from argparse import ArgumentError, ArgumentParser, Namespace
 from pathlib import Path
 
 import pytest
 
+from tox.pytest import ToxProjectCreator
 from tox.session.cmd.run.common import InstallPackageAction, SkipMissingInterpreterAction
 
 
@@ -50,3 +52,11 @@ def test_install_pkg_empty() -> None:
     argument_parser = ArgumentParser()
     with pytest.raises(ArgumentError, match=re.escape("argument --install-pkg: cannot be empty")):
         InstallPackageAction(option_strings=["--install-pkg"], dest="into")(argument_parser, Namespace(), "")
+
+
+def test_empty_report(tox_project: ToxProjectCreator) -> None:
+    proj = tox_project({"tox.ini": ""})
+    outcome = proj.run("exec", "-qq", "--", "python", "-c", "print('foo')")
+
+    outcome.assert_success()
+    outcome.assert_out_err(f"foo{os.linesep}", "")