Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transaction option in codeception doesn't roll back database changes made in tests. #7615

Closed
myleshyson opened this issue Feb 24, 2021 · 7 comments
Assignees
Labels

Comments

@myleshyson
Copy link
Contributor

myleshyson commented Feb 24, 2021

Description

I'm noticing that even though I'm setting transaction: true in codeception.yml, database operations made within tests aren't rolled back after the test is done. Here's the test file i'm running. There's no modules or plugins enabled for this test instance.

<?php

namespace tests\integration;

use Codeception\Test\Unit;
use craft\elements\Entry;
use tests\fixtures\LocationFixture;
use tests\fixtures\ProviderFixture;

class GmbModuleTest extends Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;

    public function testCreatedLocationTriggersQueue()
    {
        $section = \Craft::$app->getSections()->getSectionByHandle('locations');
        $location = new Entry();
        $location->sectionId = $section->id;
        $location->title = 'Some New Location';
        $location->typeId = $section->getEntryTypes()[0]->id;
        $location->enabled = true;
        \Craft::$app->getElements()->saveElement($location);
    }
}
actor: Tester
paths:
  tests: tests
  log: tests/_output
  data: tests/_data
  support: tests/_support
  envs: tests/_envs
bootstrap: _bootstrap.php
params:
  - tests/.env
modules:
  config:
    \craft\test\Craft:
      configFile: "tests/_craft/config/test.php"
      entryUrl: "http://host.docker.internal/index.php"
      projectConfig: {
        folder: "config/project",
        reset: false
      }
      migrations: []
      plugins: []
      cleanup: true
      transaction: true
      dbSetup: { clean: true, setupCraft: true }
# Codeception Test Suite Configuration
#
# Suite for unit or integration tests.

actor: UnitTester
modules:
    enabled:
        - \craft\test\Craft
        - Asserts
        - \Helper\Unit
docker-compose exec php ./vendor/bin/codecept run integration

Steps to reproduce

  1. Write a test in which it creates a new entry.
  2. See that after the test is done running, the entry still exists within the database.

Additional info

  • Craft version: 3.6.7
  • PHP version: 7.4.14
  • Database driver & version: MySQL 8.0.23
  • Plugins & versions:
@myleshyson
Copy link
Contributor Author

Currently my workaround for this is a custom extension that starts a transaction before a test and rolls everything back afterwards.

tests/_support/TransactionExtension.php

<?php

use Codeception\Events;
use yii\db\Transaction;

class TransactionExtension extends \Codeception\Extension
{
    /**
     * @var Transaction
     */
    protected $transaction;

    public static $events = array(
        Events::TEST_BEFORE => 'beforeTest',
        Events::TEST_AFTER => 'afterTest',
    );

    // methods that handle events
    public function beforeTest(\Codeception\Event\TestEvent $e) {
        $this->transaction = \Craft::$app->getDb()->beginTransaction();
    }

    public function afterTest(\Codeception\Event\TestEvent $e)
    {
        $this->transaction->rollBack();
    }
}

tests/integration.suite.yml

# Codeception Test Suite Configuration
#
# Suite for unit or integration tests.

actor: UnitTester
extensions:
  enabled: [TransactionExtension]
modules:
    enabled:
        - \craft\test\Craft
        - Asserts
        - \Helper\Unit

@myleshyson
Copy link
Contributor Author

myleshyson commented Feb 26, 2021

Ok new update. Seems like this is happening because the Connection::EVENT_AFTER_OPEN is never getting triggered, so transactions don't happen in tests because that's what the Yii2 codeception module relies on. And it seems like that event would only ever get called if there's not a PDO connection already established.

The above workaround was actually interfering with fixtures as well, so what I ended up doing to get everything (fixtures, projectConfig, transactions) working together is manually triggering a Connection::EVENT_AFTER_OPEN event before each test, which ensured the yii2 modules picked up connections properly and thus rolled back properly. So new workaround currently looks like:

tests/_support/Helper/MyModule.php

<?php


namespace Helper;


use Codeception\TestInterface;
use craft\test\Craft;
use yii\db\Connection;

class MyModule extends Craft
{
    public function _before(TestInterface $test)
    {
        parent::_before($test);
        \Craft::$app->getDb()->trigger(Connection::EVENT_AFTER_OPEN);

    }
}

codeception.yml

actor: Tester
paths:
  tests: tests
  log: tests/_output
  data: tests/_data
  support: tests/_support
  envs: tests/_envs
bootstrap: _bootstrap.php
params:
  - tests/.env
modules:
  config:
    \Helper\MyModule:
      configFile: "tests/_craft/config/test.php"
      entryUrl: "http://host.docker.internal/index.php"
      projectConfig: {
        folder: "config/project",
        reset: false
      }
      migrations: []
      plugins: []
      cleanup: true
      transaction: true
      dbSetup: { clean: true, setupCraft: true }

@angrybrad
Copy link
Member

Thanks for that... there probably is some wonkiness here we'll have to look into, either in Yii2's codeception module or how we're extending it.

@myleshyson
Copy link
Contributor Author

I'm gonna close this. For anybody else finding themselves here I ended up just replacing codeception entirely with craft-pest. Way simpler to setup and transactions work great.

@myleshyson
Copy link
Contributor Author

Ok looping back to this. Pest is fantastic, but it's also missing some great bells and whistles that Codception comes with. Just opened a pull request to actually try and address the underlying issue.

@angrybrad
Copy link
Member

Thanks for the PR - tested and merged. It will be included in the next release!

@brandonkelly
Copy link
Member

Craft 5.2.7 is out with this. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants