Search code examples
behatsymfony

Behat 3.1 - multiple contexts, second context class not found


I am having such behat.yml

default:
  autoload:
   #'': %paths.base%/tests/AppBundle/features/user_registration/bootstrap
   #'': %paths.base%/tests/AppBundle/features/user_login/bootstrap
   [ %paths.base%/tests/AppBundle/features/user_registration/bootstrap, %paths.base%/tests/AppBundle/features/user_login/bootstrap ]
  formatters:
      progress: ~
  suites:
     app_features:
       #paths:
         #features: %paths.base%/tests/AppBundle/features
       paths: [ %paths.base%//tests/AppBundle/features ]
       contexts:
         #- tests\AppBundle\user_registration\UserRegistrationContext
         - UserRegistrationContext
         - UserLoginContext

  #suites:
   #   default:
    #      contexts:
     #         - FeatureContext:
      #            session:   '@session'
  extensions:
    Behat\Symfony2Extension: ~

Also having this folder structure:

enter image description here

With UserRegistrationContext class its ok, it does not throw errors. Then I added UserLoginContext and it cannot find.

I am using "behat/behat": "^3.1" in composer.json.

behat.yml file is in same level as 'tests' directory.

UserLoginContext looks like this:

<?php

use Behat\Behat\Tester\Exception\PendingException;
use Behat\Behat\Context\Context;
use Behat\Behat\Context\SnippetAcceptingContext;
use Behat\Gherkin\Node\PyStringNode;
use Behat\Gherkin\Node\TableNode;

use Behat\Mink\Driver\GoutteDriver;
use Behat\Mink\Session;


use AppBundle\Controller\UserController;


/**
 * Defines application features from the specific context.
 */
class UserLoginContext implements Context, SnippetAcceptingContext
{

    private $session;

    /**
     * Initializes context.
     *
     * Every scenario gets its own context instance.
     * You can also pass arbitrary arguments to the
     * context constructor through behat.yml.
     */
    public function __construct()
    {
        // Choose a Mink driver. More about it in later chapters.
        $driver = new GoutteDriver();
        $this->session = new Session($driver);
    }

}

Why the UserLoginContext is not found?

Update

I noticed that if I do like this - leave one contexts, then UserLoginContext is found:

default:
  autoload:
   #'': %paths.base%/tests/AppBundle/features/user_registration/bootstrap
   '': %paths.base%/tests/AppBundle/features/user_login/bootstrap
   #[ %paths.base%/tests/AppBundle/features/user_registration/bootstrap, %paths.base%/tests/AppBundle/features/user_login/bootstrap ]
  formatters:
      progress: ~
  suites:
     app_features:
       #paths:
         #features: %paths.base%/tests/AppBundle/features
       paths: [ %paths.base%//tests/AppBundle/features ]
       contexts:
         #- tests\AppBundle\user_registration\UserRegistrationContext
         #- UserRegistrationContext
         - UserLoginContext

  #suites:
   #   default:
    #      contexts:
     #         - FeatureContext:
      #            session:   '@session'
  extensions:
    Behat\Symfony2Extension: ~

Update

Temporary solution I found - to create a new profile for each context. But I guess its not how it should be, but still will show how I have done:

user_login:
  autoload:
   '': %paths.base%/tests/AppBundle/features/user_login/bootstrap
  formatters:
      progress: ~
  suites:
     app_features:
       paths: [ %paths.base%//tests/AppBundle/features ]
       contexts:
         - UserLoginContext
  extensions:
    Behat\Symfony2Extension: ~

And then run with --profile parameter:

sudo vendor/behat/behat/bin/behat --profile user_login

The small problem is that when I will want to run all tests, I will have to run many commands. Also config repetition. Still waiting for better solution.


Solution

  • Here I noticed small text which helped a bit.

    http://docs.behat.org/en/v3.0/guides/6.profiles.html

    Using behat.yml to autoload will only allow for PSR-0. You can also use composer.json to autoload, which will also allow for PSR-4

    Shame for behat - they really would need to write more about this, cause new user would not understand at all how to use it together with composer.json.

    What I have done:

    • added namespace for the UserLoginContext class same as folder structure

      namespace Tests\AppBundle\features\user_login\bootstrap;

    • Added this namespace to behat.yml near contexts:

    .

    # for each context class - new profile.
    
    default:
      autoload:
       '': %paths.base%/tests/AppBundle/features/user_registration/bootstrap
      formatters:
          progress: ~
      suites:
         app_features:
           #paths:
             #features: %paths.base%/tests/AppBundle/features
           paths: [ %paths.base%//tests/AppBundle/features ]
           contexts:
    
             - UserRegistrationContext
             - Tests\AppBundle\features\user_login\bootstrap\UserLoginContext
    
      #suites:
       #   default:
        #      contexts:
         #         - FeatureContext:
          #            session:   '@session'
      extensions:
        Behat\Symfony2Extension: ~
    

    Also those who have not in their composer.json, need to add this:

    "autoload-dev": {
            "psr-4": {
                "Tests\\": "tests/"
            }
        },
    
    • Ran

      composer dump-autoload -o

    I am lucky that I have experience with PSR-4 and could guess the solution and that I had time to think and experiment.