4

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.)

Dan McNevin
  • 22,278
  • 5
  • 35
  • 28

5 Answers5

8

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

Evolve
  • 8,939
  • 12
  • 51
  • 63
3

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.

Shane Liebling
  • 248
  • 1
  • 3
  • Seems reasonable. I was sort of hoping there would be some magical gem that would mock a LDAP sever that I couldn't find on github, rubyforge, or google so I didn't actually have to do the work. I am trying to work through all of the testing options available to Rails and feeling kind of overwhelmed by all the choices and strong opinions out there. I do like your explanation of the different roles of the different testing frameworks, though, so I am going to accept this answer. Thanks! – Dan McNevin Sep 22 '09 at 18:12
2

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
Dan McNevin
  • 22,278
  • 5
  • 35
  • 28
1

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.

Glenjamin
  • 7,150
  • 6
  • 25
  • 26
  • That is awesome. Up to now, I've just been running a test LDAP server on 3389 and then basically dropping and recreating the whole root tree before each test. This should be very helpful! – Dan McNevin Oct 28 '10 at 16:26
0

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

Matt Mencel
  • 285
  • 3
  • 11
  • I am late to the testing game (the upgrade to 2.3.4 broke one of my applications, so I decided it was time to start writing some tests..) so I am not very well versed in all the techniques that people use (eg. I've heard the term stub, but that's about as far as my knowledge goes), so I was thinking there was an easy and acceptable best practice that I just didn't know about rather than some complicated test LDAP server solution. But, no one yet has answered, so maybe there's not! – Dan McNevin Sep 22 '09 at 11:14