Question

I am trying to write some cucumber tests for my application that uses Authlogic for authentication, but actually stores users in a LDAP server.

The application seems to work fine, but where I am running into trouble is writing tests for it (I know, I know, I should've wrote the tests first.) It's easy to have a test database where the data is cleared out after each run, but not so easy with an LDAP server.

My idea was to write a rake task (like rake ldap:test:prepare) to refresh the ldap server before each run (or make it a dependency), but that seems pretty time consuming when I am working on tests (and makes autotest near impossible.)

Is there a better way to do this? Is there a ruby-based fake LDAP server I can bind to with pre-defined fixtures? Is there some other even more elegant solution that I am not thinking of? (not using LDAP isn't an option.)

Was it helpful?

Solution

So in general Cucumber tests are for integration and acceptance testing. That being the case it is supposed to test the system end-to-end, so it should be testing the LDAP integration as well. My suggestion, if you can swing it, would be to set up another LDAP server and do a periodic dump from your live one to set it up with whatever test data you need.

I will say though that your first idea of having the dependency that refreshes the LDAP db before each run is the "right" way to do it. Integration/acceptance testing is supposed to take a long time. It is testing the entirety of the functionality of the system, not just small (unit) pieces.

Cucumber is not a unit testing framework, and shouldn't be used in that manner. If your application broke after migrating to 2.3.4 because you didn't have tests I think you should get in there and start writing some unit tests...

Now this is my personal bias, but if you have no unit tests in place I would take a look at RSpec. If you like the english-like syntax of Cucumber, RSpec will definitely feel similar. If you are already somewhat tested in Test::Unit, I would definitely suggest bringing Shoulda to the party or possibly Context/Matchy (all of which are available on github) to get the RSpec feel within the Test::Unit framework.

OTHER TIPS

Have a go using Ladle as a test LDAP server: "Ladle dishes out steaming helpings of lightweight directory access (LDAP) for use in testing with rspec, cucumber, or any other ruby test framework".

https://github.com/NUBIC/ladle

I was finally able to get around to basically cleaning the ldap server before each cucumber scenario was run. I did this by adding a hook into cucumber

Before do |scenario|
  puts "Cleaning Up LDAP Server"
  LdapConnect.new(:admin => true).clear_users!
end

And then my LdapConnect class (since multiple models might need to touch the ldap server, I can just pass around this object). I am using the ruby-net-ldap gem for LDAP interaction

class LdapConnect

  def initialize(params = {})
    ldap_config = YAML.load_file("#{RAILS_ROOT}/config/ldap.yml")[RAILS_ENV]
    ldap_options = params.merge({:encryption => :simple_tls})

    @ldap = Net::LDAP.new(ldap_options)
    @ldap.host = ldap_config["host"]
    @ldap.port = ldap_config["port"]
    @ldap.base = ldap_config["base"]
    @ldap.auth ldap_config["admin_user"], ldap_config["admin_password"] if params[:admin] 
  end

  def ldap
    @ldap
  end

  def clear_users!(base = "ou=people,dc=test,dc=com")
    raise "You should ONLY do this on the test enviornment! It will clear out all of the users in the LDAP server" if RAILS_ENV != "test"
    if @ldap.bind
      @ldap.search(:filter => "cn=*", :base => base) do |entry|
        @ldap.delete(:dn => entry.dn)
      end
    end
  end

end

So, my cucumber feature looks something like:

Feature: Check to make sure users can login
  In order to make sure users can login with the LDAP server
  As a user
  I want to make sure the user can login

  Background:
    Given I have the following users
    | email | password | user_class | first_name | last_name |
    | external@test.com | right_password | externalPerson | external | person |
    | internal@test.com | right_password | internalPerson | internal | person |
    | admin@test.com | right_password | adminPerson | admin | person |

  Scenario: Success Login Check
    Given I am logged in as "external@test.com" with password "right_password"
    Then I should be on the homepage

And finally the steps

Given /^I have the following users$/ do |table|
  # table is a Cucumber::Ast::Table
  table.hashes.each do |hash|
    hash[:password_confirmation] == hash[:password] unless hash[:password_confirmation]
    User.create(hash)
  end
end

Given /^I am logged in as "([^\"]*)" with password "([^\"]*)"$/ do |email, password|
  visit login_url  
  fill_in "Email", :with => email  
  fill_in "Password", :with => password  
  click_button "Login" 
end

I've just been looking into this myself, and have come across the rather under-the-radar fakeldap gem.

http://github.com/aanand/fakeldap http://rubygems.org/gems/fakeldap

I may add to this answer with some experience after i've used it.

Not really an answer but...I'm working on a very similar problem, testing LDAP authentication and lookup code with cucumber. Have you looked into using a stub in your test? I was thinking of stubbing my LDAP responses...just haven't figured out how to do it yet.

Matt

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top