1

I'm starting with BDD (cucumber + capybara + selenium chromedriver) and TDD (rspec) with factory_bot and I'm getting an error on cucumber features - step_definitions.

uninitialized constant User (NameError)

With TDD, everything is ok, the factory bot is working fine. The problem is with the cucumber.

factories.rb

FactoryBot.define do

    factory :user_role do
        name {"Admin"}
        query_name {"admin"}
    end

    factory :user do
        id {1}
        first_name {"Mary"}
        last_name {"Jane"}
        email {"mary_jane@gmail.com"}
        password {"123"}
        user_role_id {1}
        created_at {'1/04/2020'}
    end
end

support/env.rb

require 'capybara'
require 'capybara/cucumber'
require 'selenium-webdriver'
require 'factory_bot_rails'

Capybara.register_driver :selenium do |app|
    Capybara::Selenium::Driver.new(app, browser: :chrome)
end

Capybara.configure do |config|
    config.default_driver = :selenium
end

Capybara.javascript_driver = :chrome

World(FactoryBot::Syntax::Methods)

And the problem is happening here

support/hooks.rb

Before '@admin_login' do
    @user = create(:user)
end

step_definitions/admin_login.rb

Given("a registered user with the email {string} with password {string} exists") do |email, password|
    @user
end

I don't know why, but I can't access the user using cucumber and factory_bot.

Anybody could help me please?

I think I need to configure something on the cucumber.

What do you think guys?


Juny
  • 191
  • 1
  • 1
  • 15

2 Answers2

1

First of all Luke is correct about this being a setup issue. The error is telling you that the User model cannot be found which probably means Rails is not yet loaded. I can't remember the exact details of how cucumber-rails works but one of the things it does is to make sure that each scenario becomes an extension of a Rails integration test. This ensures that all of the Rails auto-loading has taken place and that these things are available.

Secondly I'd suggest you start simpler and use a step to create your registered user rather than using a tag. Using tags for setup is a Cucumber anti-pattern.

Finally, and more controversially I'd suggest that you don't use factory-bot when cuking. FactoryBot uses a separate configuration to create model objects directly in the datastore. This bypasses any application logic around the creation of these objects, which means the objects created by FactoryBot are going to end up being different from the objects created by your application. In real life object creation involves things like auditing, sending emails, conditional logic etc. etc. To use FactoryBot you either have to duplicate that additional creation logic and behavior or ignore it (both choices are undesirable).

You can create objects for cuking much more effectively (and quicker) by using the following pattern.

Each create method in the Rails controller delegates its work to a service object e.g.

UserController
  def create
    @user = CreateUserService.new(params).call
  end
end

Then have your cukes use a helper module to create things for you. This module will provide tools for your steps to create users, using the above service

module UserStepHelper
  def create_user(params)
    CreateUserService.new(default_params.merge(params))
  end

  def default_params
    {
      ...
    }
  end
end
World UserStepHelper

Given 'there is a registered user' do
  @registered_user = create_user
end

and then use that step in the background of your feature e.g.

Background: 
  Given there is a registered user
  And I am an admin

Scenario: Admin can see registered users
  When I login and view users
  Then I should see a user

Notice the absence of tagging here. Its not desirable or necessary here.

You can see an extension of this approach in a sample application I did for a CukeUp talk in 2013 here https://github.com/diabolo/cuke_up/commits/master. If you follow this commit by commit starting from first commit at the bottom you will get quite a good guide to setting up a rails project with cucumber in just the first 4 or 4 commits. If you follow it through to the end (22 commits) you'll get a basic powerful framework for creating and using model objects when cuking. I realize the project is ancient and that obviously you will have to use modern versions of everything, but the principles still apply, and I use this approach in all my work and having been doing so for at least 10 years.

diabolist
  • 3,990
  • 1
  • 11
  • 15
0

So if you're using rails, it's probably advised to use cucumber-rails over cucumber. This is probably an issue where your User models have not been auto-loaded in.

Cucumber auto-loads all ruby files underneath features, with env.rb first, it's almost certainly an issue with load order / load location

Luke Hill
  • 460
  • 2
  • 10
  • I update my gemfile with cucumber-rails, but same error :( – Juny Apr 03 '20 at 15:23
  • try starting a separate project from scratch using cucumber-rails and ensuring you run the post install setup `rails generate cucumber:install` – diabolist Apr 04 '20 at 08:44