Repository: Codeception/Codeception (language: php)

Issue:
Output messages don't make sense
#### What are you trying to achieve?
I'm probably overlooking something dumb, but searching around for this hasn't produced much help.

When running tests verbosely (`-vv`, `-vvv`), i want each assertion's output to read neatly, using the Constraint's self-describing `toString()`. For example:
```php
public function _ (UnitTester $I)
{
    $I->assertThat(true, \PHPUnit\Framework\Assert::isTrue());
    $I->assertFalse(false);
}
```
i expect something like:
`I assert that true is true`
`I assert false is false`

#### What do you get instead?
The first one is especially off-putting. Why is it using the Constraint's FQN?
`I assert that true, "PHPUnit\\Framework\\Constraint\\IsTrue"`
`I assert false false`

> Provide console output if related. Use `-vvv` mode for more details.
```bash
$ php vendor/bin/codecept run Unit TestCest:default -vvv

Codeception PHP Testing Framework v5.0.12 https://stand-with-ukraine.pp.ua

Tests.Unit Tests (1) -------------------------------------------------------
Modules: Asserts
----------------------------------------------------------------------------
TestCest: Default
Signature: Tests\Unit\TestCest:default
Test: tests/Unit/TestCest.php:default
Scenario --
 I assert that true,"PHPUnit\\Framework\\Constraint\\IsTrue"
 I assert false false
 PASSED

----------------------------------------------------------------------------
Time: 00:00.513, Memory: 4.00 MB

OK (1 test, 2 assertions)
```
> Provide test source code if related

```php
/**
 * @test
 */
public function default(UnitTester $I)
{
    $I->assertThat(true, \PHPUnit\Framework\Assert::isTrue());
    $I->assertFalse(false);
}
```
### Details

* Codeception version: 5.0.12
* PHP Version: 8.1.x
* Operating System: Windows, and WSL (AlmaLinux 9.2)
* Installation type: Composer
* List of installed packages (`composer show`)
  This is the minimal functional install i can get to, but it doesn't change when i add back all my typical packages.
  ```
  behat/gherkin                       v4.9.0   Gherkin DSL parser for PHP
  codeception/codeception             5.0.12   BDD-style testing framework
  codeception/lib-asserts             2.1.0    Assertion methods used by Code...
  codeception/lib-innerbrowser        3.1.3    Parent library for all Codecep...
  codeception/lib-web                 1.0.2    Library containing files used ...
  codeception/module-asserts          3.0.0    Codeception module containing ...
  codeception/stub                    4.1.2    Flexible Stub wrapper for PHPU...
  docler-labs/codeception-slim-module 4.1.0    Codeception Module for Slim fr...
  doctrine/instantiator               2.0.0    A small, lightweight utility t...
  fig/http-message-util               1.1.5    Utility classes and constants ...
  guzzlehttp/psr7                     2.6.1    PSR-7 message implementation t...
  laravel/serializable-closure        v1.3.3   Laravel Serializable Closure p...
  masterminds/html5                   2.8.1    An HTML5 parser and serializer.
  monolog/monolog                     2.9.2    Sends your logs to files, sock...
  myclabs/deep-copy                   1.11.1   Create deep copies (clones) of...
  nikic/fast-route                    v1.3.0   Fast request router for PHP
  nikic/php-parser                    v4.17.1  A PHP parser written in PHP
  phar-io/manifest                    2.0.3    Component for reading phar.io ...
  phar-io/version                     3.2.1    Library for handling version i...
  php-di/invoker                      2.3.4    Generic and extensible callabl...
  php-di/php-di                       6.4.0    The dependency injection conta...
  php-di/phpdoc-reader                2.2.1    PhpDocReader parses @var and @...
  phpunit/php-code-coverage           9.2.29   Library that provides collecti...
  phpunit/php-file-iterator           3.0.6    FilterIterator implementation ...
  phpunit/php-invoker                 3.1.1    Invoke callables with a timeout
  phpunit/php-text-template           2.0.4    Simple template engine.
  phpunit/php-timer                   5.0.3    Utility class for timing
  phpunit/phpunit                     9.6.13   The PHP Unit Testing framework.
  psr/container                       1.1.2    Common Container Interface (PH...
  psr/event-dispatcher                1.0.0    Standard interfaces for event ...
  psr/http-factory                    1.0.2    Common interfaces for PSR-7 HT...
  psr/http-message                    1.1      Common interface for HTTP mess...
  psr/http-server-handler             1.0.2    Common interface for HTTP serv...
  psr/http-server-middleware          1.0.2    Common interface for HTTP serv...
  psr/log                             3.0.0    Common interface for logging l...
  psy/psysh                           v0.11.22 An interactive shell for moder...
  ralouphie/getallheaders             3.0.3    A polyfill for getallheaders.
  sebastian/cli-parser                1.0.1    Library for parsing CLI options
  sebastian/code-unit                 1.0.8    Collection of value objects th...
  sebastian/code-unit-reverse-lookup  2.0.3    Looks up which function or met...
  sebastian/comparator                4.0.8    Provides the functionality to ...
  sebastian/complexity                2.0.2    Library for calculating the co...
  sebastian/diff                      4.0.5    Diff implementation
  sebastian/environment               5.1.5    Provides functionality to hand...
  sebastian/exporter                  4.0.5    Provides the functionality to ...
  sebastian/global-state              5.0.6    Snapshotting of global state
  sebastian/lines-of-code             1.0.3    Library for counting the lines...
  sebastian/object-enumerator         4.0.4    Traverses array structures and...
  sebastian/object-reflector          2.0.4    Allows reflection of object at...
  sebastian/recursion-context         4.0.5    Provides functionality to recu...
  sebastian/resource-operations       3.0.3    Provides a list of PHP built-i...
  sebastian/type                      3.2.1    Collection of value objects th...
  sebastian/version                   3.0.2    Library that helps with managi...
  slim/psr7                           1.6.1    Strict PSR-7 implementation
  slim/slim                           4.12.0   Slim is a PHP micro framework ...
  symfony/browser-kit                 v6.3.8   Simulates the behavior of a we...
  symfony/console                     v6.3.8   Eases the creation of beautifu...
  symfony/css-selector                v6.3.2   Converts CSS selectors to XPat...
  symfony/deprecation-contracts       v3.4.0   A generic function and convent...
  symfony/dom-crawler                 v6.3.4   Eases DOM navigation for HTML ...
  symfony/event-dispatcher            v6.3.2   Provides tools that allow your...
  symfony/event-dispatcher-contracts  v3.4.0   Generic abstractions related t...
  symfony/finder                      v6.3.5   Finds files and directories vi...
  symfony/polyfill-ctype              v1.28.0  Symfony polyfill for ctype fun...
  symfony/polyfill-intl-grapheme      v1.28.0  Symfony polyfill for intl's gr...
  symfony/polyfill-intl-normalizer    v1.28.0  Symfony polyfill for intl's No...
  symfony/service-contracts           v2.5.2   Generic abstractions related t...
  symfony/string                      v6.3.8   Provides an object-oriented AP...
  symfony/var-dumper                  v6.3.8   Provides mechanisms for walkin...
  symfony/yaml                        v6.3.8   Loads and dumps YAML files
  theseer/tokenizer                   1.2.2    A small library for converting...
  ```
* Composer:
  ```json
  {
    "require": {
      "php": "^8.1.12",
      "ext-json": "*",
      "ext-mbstring": "*",
      "ext-openssl": "*",
      "monolog/monolog": "^2.8", 
      "php-di/php-di": "^6.4", 
      "slim/slim": "4.*" 
    },
    "require-dev": {
      "codeception/codeception": "^5.0", 
      "codeception/module-asserts": "^3.0", 
      "docler-labs/codeception-slim-module": "^4.0" 
    }
  }
  ```

* Suite configuration:
```yml
# Unit.suite.yml

actor: UnitTester
modules:
  enabled:
    - Asserts
step_decorators: ~
```




Discussion / hints:
This is how Codeception step works.
It converts action name to words and appends all arguments.
It looks much better when you use a module that was properly designed for Codeception:
```
I am on page "/about"
I click "button"
I see "some text"
```

I aggree that Asserts step output is ugly, but there is not much we can do short of rewriting Asserts module and/or Codeception.

`assertThat` is the only method that takes constraint as parameter, the output could be improved by modifying Step class to call `toString` - https://github.com/Codeception/Codeception/blob/7d754d1891316d8c525fdb8a0ad7811c5cb9f955/src/Codeception/Step.php#L169-L179

Generating step outputs from method names is one of the main Codeception ideas, I don't thing that it can be replaced with something similar to Constraint.

i figured the Assert language is coming from the underlying PHPUnit. No big deal there.

Adjusting to handle Constraint objects would be fantastic. Seems like a simple thing if you'd like me to check out and submit a PR.

Fix patch:
diff --git a/src/Codeception/Step.php b/src/Codeception/Step.php
index 8d943400dd..fa28ceb09d 100644
--- a/src/Codeception/Step.php
+++ b/src/Codeception/Step.php
@@ -10,6 +10,7 @@
 use Codeception\Step\Meta as MetaStep;
 use Codeception\Util\Locator;
 use Exception;
+use PHPUnit\Framework\Constraint\Constraint;
 use PHPUnit\Framework\MockObject\MockObject;
 use RuntimeException;
 use Stringable;
@@ -171,8 +172,10 @@ protected function stringifyArgument(mixed $argument): string
                 $argument = $argument->getOutput();
             } elseif (method_exists($argument, '__toString')) {
                 $argument = (string)$argument;
-            } elseif ($argument::class == 'Facebook\WebDriver\WebDriverBy') {
+            } elseif ($argument::class === 'Facebook\WebDriver\WebDriverBy') {
                 $argument = Locator::humanReadableString($argument);
+            } elseif ($argument instanceof Constraint) {
+                $argument = $argument->toString();
             } else {
                 $argument = $this->getClassName($argument);
             }


Test patch:
diff --git a/tests/unit/Codeception/StepTest.php b/tests/unit/Codeception/StepTest.php
index e2278f84a2..76fdb5914f 100644
--- a/tests/unit/Codeception/StepTest.php
+++ b/tests/unit/Codeception/StepTest.php
@@ -6,6 +6,7 @@
 use Codeception\Step\Argument\FormattedOutput;
 use Codeception\Stub;
 use Facebook\WebDriver\WebDriverBy;
+use PHPUnit\Framework\Constraint\Constraint;
 use PHPUnit\Framework\TestCase;
 
 class StepTest extends TestCase
@@ -139,4 +140,14 @@ public function testFormattedOutput()
         $output = $step->toString(200);
         $this->assertSame('argument "some formatted output"', $output);
     }
+
+    public function testConstraintOutput(): void
+    {
+        $argument = Stub::makeEmpty(Constraint::class);
+        $argument->method('toString')->willReturn('is a constraint');
+
+        $step = $this->getStep(['this', [$argument]]);
+        $output = $step->toString(200);
+        $this->assertSame('this "is a constraint"', $output);
+    }
 }