redmatter/Codeception-MultiDb

Codeception\Extension\MultiDb Not Defined

Closed this issue · 8 comments

Hi There

Thank you for contributing this extension. It is something I will definitely be needing to complete some tests for my project.

I'm having trouble initializing a simple test to get off the ground with this module. Some basic info:

Composer.json:

{
    "require": {
        "codeception/codeception": "^2.1",
        "redmatter/codeception-multidb": " ~2.0@dev"
    }
}

Here's my configurations:

acceptance.suite.yml

class_name: AcceptanceTester
modules:
    enabled:
        - WebDriver:
            url: 'http://dev.mysite..net'
            port: 5454
            browser: phantomjs
            window_size:  1248x900
            capabilities:
              javascriptEnabled: true
              browserConnectionEnabled: true
              elementScrollBehavior: true
        - \Helper\Acceptance
        - Codeception\Extension\MultiDb
    config:
        Codeception\Extension\MultiDb:
          connectors:
            Primary:
              dsn: 'mysql:host=x.y;dbname=db1'
              user: 'myUser'
              password: 'myPass'
              populate: false
              cleanup: false
            Secondary:
              dsn: 'mysql:host=x.y;dbname=db2'
              user: 'myUser'
              password: 'myPass'
              populate: false
              cleanup: false

codeception.yml

actor: Tester
paths:
    tests: tests
    log: tests/_output
    data: tests/_data
    support: tests/_support
    envs: tests/_envs
settings:
    bootstrap: _bootstrap.php
    colors: true
    memory_limit: 1024M
extensions:
    enabled:
      - Codeception\Extension\RunFailed
      - Codeception\Extension\MultiDb

My test is pretty simple:

/**
     *
     *
     * @param FunctionalTester $I
     */
    public function checkForTemp(\AcceptanceTester $I)
    {
        $I->amConnectedToDb('Secondary');

        $I->seeInDatabase('leads', array(
            'first_name'   => 'Miles',
            'last_name'    => 'Davis',
            'phone_number' => 8788675309
        ));
    }

I've tried a number of different things to fix the issue like doing composer dump-autoload and composer install.

I've also tried working in the _bootstrap.php file to add a class autoload per the Codeception documents here (http://codeception.com/docs/reference/Autoload#CodeceptionUtilAutoload)

I wasn't successful in doing that.

I am using Codeception 2.1 which I know is new / beta per your readme here.

Any ideas on how I can get this module working?

@drmmr763 Please can you let me know what message you get when you run the test.
Also; have you initialised the test by doing a build, as described here?

Please can you also have a look at the example in this repo? Another option would be to make a copy of that and apply your changes. Then follow the codeception doc mentioned above.

Hi @codemedic

Thanks for you direction here. I was finally able to get this working. I think I might have had a number of minor issues causing this problem. Here's what I ended up with:

  1. I had not ran the build command as you asked at the beginning. When I tried to do that, I got the same error that the MultiDb class couldn't be located.

  2. I finally fixed the undefined class issue by including Composer's autoloader into tests\_bootstrap.php:

<?php

$path = dirname(__DIR__) . '/vendor/autoload.php';
require_once($path);

I don't know if this is actually the "correct" method for including the classes. I feel like since I was able to run Codeception tests without MultiDb, and those classes are clearly already being autoloaded that adding the autoloader this way might be unnecessary.

But, can't argue with results -- Once I added the require to the autoloader the undefined class errors went away.

Some other notes / questions:

  • I found I had to switch out database assertions like seeInDatabase to the MultiDb equivalents: seeInDb. Is that expected? I had thought the existing DB assertions would continue function. Luckily I don't have a lot of tests written so it won't be hard to refactor over, but I'm still not sure if its necessary.
  • If it is necessary, let me know and I'd be happy to add to the wiki here to document the assert methods if you want the help. I can add them to the examples as well.

Thanks again for your help and I'd like to return the favor.

@drmmr763 I am surprised that you had to add the require for autoload.php. The example that I pointed you to does not have that, and it is functional.

I wonder if it is something to do with the way you are invoking the test run. If you visualise the below tree as my project structure, say within /home/redmatter/ProductsProject, I would cd into /home/redmatter/ProductsProject/codeception before invoking my tests. Then I run the command vendor/bin/codecept run.

I always keep composer separate from the main project, and at times I check it in within a different tree (i.e not within the main project's tree). From what I remember from my early days with codeception, life with it got a bit easier after I realised it is better to invoke the codecept script that exists within vendor/bin. I really can't remember the exact details.

├── apache.conf
├── app
│   ├── AppCache.php
│   ├── ...
│   └── SymfonyRequirements.php
├── bin
│   └── doctrine
├── composer.json
├── composer.lock
├── src
│   └── Redmatter
│       └── ProductsBundle
├── web
│   ├── app_dev.php
│   ├── app.php
│   └── robots.txt
└── codeception
    ├── codeception.dist.yml
    ├── composer.json
    ├── composer.lock
    ├── tests
    │   ├── Product
    │   │   ├── ProductCreationCest.php
    │   │   ├── ProductDeletionCest.php
    │   │   ├── ProductListRetrievalCest.php
    │   │   ├── ProductReplacementCest.php
    │   │   ├── ProductRetrievalCest.php
    │   │   ├── ProductTester.php
    │   │   └── _bootstrap.php
    │   ├── Product.suite.yml
    │   ├── _bootstrap.php
    │   ├── _data
    │   ├── _extensions
    │   ├── _output
    │   └── _support
    └── vendor
        ├── autoload.php
        ├── codeception
        ├── composer
        ├── ...
        ├── redmatter
        ├── ...
        ├── symfony
        └── bin
            └── codecept -> ../codeception/codeception/codecept

On the seeInDatabase and seeInDb, it was by purpose as I didn't want to clobber the existing functionality for those who would be slowly migrating to MultiDb.

Please do submit a PR for the assert methods; much appreciated. As you would have already realised, there is some amount of documentation in the form of PHPDoc. I wonder if it is worth using some sort of document generation based on that, and then update the PHPDoc (as and when needed). The generated document can be then checked in under a doc folder.

Hi Again @codemedic

So I'm still running into a little bit of pathing odd-ness. I'm wondering if it might have to do with me using the codecept.phar instead of running from the bin directory as you mentioned here.

For example, I just started getting this error:

php codecept.phar run acceptance HomePageLeadCest.php --steps --xml=daily.xml --debug
  [PHPUnit_Framework_Exception]
  Argument 1 passed to Codeception\Extension\MultiDb::_before() must be an instance of Codeception\TestCase, instance of Codeception\Test\Ce
  st given, called in /home/project-dir/vendor/codeception/codeception/src/Codeception/Subscriber/Module.php on line 58 and defin
  ed

Its complaining here about the instance of the test case. The odd thing about this error is it seems to be slightly environment based. My localhost will throw it, but my dev server will not. Yet my production server which is the exact same environment (php version, phantomjs version, phpunit version, codeception version), and it does throw this error. It's so odd!

I can try to migrate the paths over to what you've recommended here but it would be a large refactoring :(

What version of codeception are you running?

Same version on all 3 environments:

php codecept.phar --version
Codeception version 2.1.7

here's a full stack trace:

Exception trace:
 () at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codeception/Subscriber/ErrorHandler.php:60
 Codeception\Subscriber\ErrorHandler->errorHandler() at /var/www/public/AdvancedMedicalTests/vendor/redmatter/codeception-multidb/src/CodeceptionExtension/MultiDb.php:92
 Codeception\Extension\MultiDb->_before() at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codeception/Subscriber/Modul.php:58
 Codeception\Subscriber\Module->before() at n/a:n/a
 call_user_func() at /var/www/public/AdvancedMedicalTests/vendor/symfony/event-dispatcher/EventDispatcher.php:174
 Symfony\Component\EventDispatcher\EventDispatcher->doDispatch() at /var/www/public/AdvancedMedicalTests/vendor/symfony/event-dispatcher/EventDisatcher.php:43
 Symfony\Component\EventDispatcher\EventDispatcher->dispatch() at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codecepion/PHPUnit/Listener.php:124
 Codeception\PHPUnit\Listener->fire() at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codeception/PHPUnit/Listener.php95
 Codeception\PHPUnit\Listener->startTest() at /var/www/public/AdvancedMedicalTests/vendor/phpunit/phpunit/src/Framework/TestResult.php:327
 PHPUnit_Framework_TestResult->startTest() at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codeception/Test/Test.php:6
 Codeception\Test\Test->run() at /var/www/public/AdvancedMedicalTests/vendor/phpunit/phpunit/src/Framework/TestSuite.php:747
 PHPUnit_Framework_TestSuite->run() at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codeception/PHPUnit/Runner.php:98
 Codeception\PHPUnit\Runner->doEnhancedRun() at /var/www/public/AdvancedMedicalTests/vendor/codeception/codeception/src/Codeception/SuiteManager.hp:152
 Codeception\SuiteManager->run() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/src/Codeception/Codecept.php:203
 Codeception\Codecept->runSuite() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/src/Codeception/Codecept.php:172
 Codeception\Codecept->run() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/src/Codeception/Command/Run.php:184
 Codeception\Command\Run->execute() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/vendor/symfony/console/Command/Command.php:256
 Symfony\Component\Console\Command\Command->run() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/vendor/symfony/console/Applicationphp:791
 Symfony\Component\Console\Application->doRunCommand() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/vendor/symfony/console/Appliction.php:186
 Symfony\Component\Console\Application->doRun() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/vendor/symfony/console/Application.pp:117
 Symfony\Component\Console\Application->run() at phar:///var/www/public/AdvancedMedicalTests/codecept.phar/codecept:34
 require_once() at /var/www/public/AdvancedMedicalTests/codecept.phar:7

Just realized that version 2.2 release makes some mention of the Testcase that I'm seeing:

http://codeception.com/06-03-2016/codeception-2.2-is-here.html

I can try updating and see if that resolves it.

Okay yes - updating to Codeception 2.2 fixed the issue! And I can still run from the .phar as well. So yay, crisis averted. Sorry for blowing up the notifications. I'll try to find some time this weekend to dig into the documentation as discussed earlier. Thanks again for all your help!

I haven't yet tried MultiDb with v2.2. from the release note, prima facie, there are no breaking changes.
Do let me know if you notice any.

On the codecept.phar usage; in my workflow, I rely much on composer to bring in any component, be it codeception itself or any other component for it. I have found that to be less problematic; but then, I have not tried the phar route lately.

Glad your issues are resolved.