Search code examples
phpcomposer-phpcodeception

Codeception project can't find AcceptanceTester


I am creating a new project from scratch on a Mac Catalina 10.15 with php v7.3.27 and composer v2.0.12. I have created a Codeception project before but on a different computer. I followed the quickstart guide using acceptance tests.

I generated the page objects using "php vendor/bin/codecept generate:pageobject acceptance " and generated the Cests using "php vendor/bin/codecept generate:cest acceptance "

When I try to run any tests, it says that the class isn't found. If I hover over my pages or over the word AcceptanceTester, it does not link me to anything. My project looks like this:

tests
   > data
   > output
   v support
     v _generated
       AcceptanceTesterActions.php
       FunctionalTesterActions.php
       UnitTesterActions.php
   > Helper
   > Page/Acceptance
      CustomerSignupHomePage.php
    AcceptanceTester.php
    FunctionalTester.php
    UnitTester.php
   v acceptance
      CustomerSignupCest.php

I realized I didn't have a .bashrc in my home dir, so I created one and I updated the bash_profile similar to what I had on my working computer:

#Global composer bin

export $PATH=~/.composer/vendor/bin:$PATH
export $PATH="$HOME/.composer/vendor/bin:$PATH"

cat .bash_profile
#alias composer="php /usr/local/bin/composer.phar"
  
export PATH="./composer/vendor/bin/:$PATH"

export PATH="/usr/local/opt/[email protected]/bin:$PATH"
export PATH="/usr/local/opt/[email protected]/sbin:$PATH"
~                                                  

My codeception.yml looks like this:

    tests: tests
    output: tests/_output
    data: tests/_data
    support: tests/_support
    envs: tests/_envs
actor_suffix: Tester
extensions:
    enabled:
        - Codeception\Extension\RunFailed

My composer.json looks like this:

    "require-dev": {
        "codeception/codeception": "^4.1",
        "codeception/module-phpbrowser": "^1.0.0",
        "codeception/module-asserts": "^1.0.0"
    },
    "require":{
        "ext-zip": "*",
        "guzzlehttp/guzzle": "^7.2",
        "vlucas/phpdotenv": "^5.2"
    },
    "autoload": {
        "psr-4": {
            "Tests\\Support\\": "tests/_support/"
        }
    }
}

My one Cest file looks like this:


use Tests\Support\Page\Acceptance\CustomerSignupHomePage;

class CustomerSignupCest
{

    const ADDRESS = "100 Silmarillion Trail, Austin TX 78739";
    const NAME = "POC Automation Tester";
    const PHONE = "512-203-5555";

    /**
     * signUp
     *
     * @param AcceptanceTester $I
     * @return void
     */
    public function signUp(AcceptanceTester $I)
    {
        $I->wantToTest("the signup flow");
        CustomerSignupHomePage::fillGetQuickAndEasyPrice($I, self::ADDRESS, self::NAME, self::PHONE);
    }
}

My page class looks like this:


namespace Tests\Support\Page\Acceptance;

class CustomerSignupHomePage
{
    // include url of current page
    public static $URL = 'https://dev-www.<mycompany>.com';

    /**
     * Declare UI map for this page here. CSS or XPath allowed.
     * public static $usernameField = '#username';
     * public static $formSubmitButton = "#mainForm input[type=submit]";
     */
    const ADDRESS_INPUT = "#streetAddress";
    const SEE_PRICE_BUTTON = ".js-submitButton";
    const NAME_INPUT = ".js-fullNameInput";
    const PHONE_INPUT = ".js-phoneInput";
    
    /**
     * fillGetQuickAndEasyPrice
     *
     * @param AcceptanceTester $I
     * @param mixed $address
     * @param mixed $name
     * @param mixed $phone
     * @return void
     */
    public static function fillGetQuickAndEasyPrice(AcceptanceTester $I, $address, $name, $phone)
    {
        $I->waitForElement(self::ADDRESS_INPUT);
        $I->fillField(self::ADDRESS_INPUT, $address);
        $I->click(self::SEE_PRICE_BUTTON);
        $I->fillField(self::NAME_INPUT, $name);
        $I->fillField(self::PHONE_INPUT, $phone);
        $I->click(self::SEE_PRICE_BUTTON);
    }

    /**
     * Basic route example for your current URL
     * You can append any additional parameter to URL
     * and use it in tests like: Page\Edit::route('/123-post');
     */
    public static function route($param)
    {
        return static::$URL.$param;
    }

    /**
     * @var \AcceptanceTester;
     */
    protected $acceptanceTester;

    public function __construct(\AcceptanceTester $I)
    {
        $this->acceptanceTester = $I;
    }

}

If I try to run the tests, I get this error:

[TypeError] Argument 1 passed to Tests\Support\Page\Acceptance\CustomerSignupHomePage::fillGetQuickAndEasyPrice() must be an instance of Tests\Support\Page\Acceptance\AcceptanceTester, instance of AcceptanceTester given, called in /Users/julie/workspaces/Codeception-Demo/tests/acceptance/CustomerSignupCest.php on line 21
 

My AcceptanceTester.php is the one automatically generated by codeception:



/**
 * Inherited Methods
 * @method void wantToTest($text)
 * @method void wantTo($text)
 * @method void execute($callable)
 * @method void expectTo($prediction)
 * @method void expect($prediction)
 * @method void amGoingTo($argumentation)
 * @method void am($role)
 * @method void lookForwardTo($achieveValue)
 * @method void comment($description)
 * @method void pause()
 *
 * @SuppressWarnings(PHPMD)
*/
class AcceptanceTester extends \Codeception\Actor
{
    use _generated\AcceptanceTesterActions;

    /**
     * Define custom actions here
     */
}

My Cest file and Page file doesn't see AutomationTester at all. If I start typing $I-> it does not see any codeception methods. I have added the Codeception marketplace extension to Vscode. If I hover over AcceptanceTester in the param of my method, it doesn't take me to the class file. If I hover over the page, it doesn't take me to the page object file. It is like I am flying blind. The error happens in vscode and outside vscode in terminal.

I have tried:

  • Adding "use AcceptanceTester" either above or below classname and with relative path/absolute path, does not work
  • Restarting vscode
  • Running build commands
  • Trying to extend AcceptanceTester (doesn't work)
  • Googling and looking at other SO answers
  • Removing namespace from the page (makes it worse, says page not found then)
  • Commenting out the call to the page object and using var_dump("hello world")- makes the tests pass but obviously then tests do nothing
  • realized i also had zshell and but also no .zshrc so tried the same commands as the bash ones. Also sourced the bash profile
  • ran the autodump command
  • Tried to follow the error message exactly and moved the AcceptanceTester file in the /Page/Acceptance folder, but then when I run tests, the error changes to " AcceptanceTester class doesn't exist in suite folder. Run the 'build' command to generate it" If I run build, then it puts the AcceptanceTester.php right back where it was!
  • Blew out my whole project and started over with no page files, only the single class file, following the quickstart docs with the bootstrap instructions. The Cest still doesn't see AcceptanceTester $I as related to the AcceptanceTester.php and says "Call to undefined method AcceptanceTester::waitForElement". Retried steps from above with no luck.
  • Pushed everything up to git, then closed on the working computer and got a totally different error: The "/Users/julielaursen/git/Codeception-Demo/tests/functional/" directory does not exist. I have not set up the project for functional but for acceptance.

Solution

  • You need to specify backslash before AcceptanceTester class name in the methods signatures to find class in the root namespace:

    public function signUp(\AcceptanceTester $I)

    public static function fillGetQuickAndEasyPrice(\AcceptanceTester $I, $address, $name, $phone)