Testing PyROOT is Working

If you’ve compiled ROOT to use python, you need to find out if it’s working correctly. The following code will do that:

root [0] gSystem->Load("libPyROOT")
(int)0
root [1] TPython::Exec("print 1+1")
2
(Bool_t)1

Then to check that you can load ROOT into python, try:

[ ~]$ python
Python 2.7.7 (default, Jun 23 2014, 13:28:36) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import ROOT
>>> import BAD_LIBRARY
Traceback (most recent call last):
  File "", line 1, in 
ImportError: No module named BAD_LIBRARY
>>> 

We didn’t get any errors when loading ROOT, that’s what we wanted.

Handy Trick

If you have some sample code in a ruby file that you want to run ONLY when that file is called directly, enclose it in the following if statement.

if __FILE__ == $0
  puts "Print stuff out here to test this file"
end

The __FILE__ is an environment variable that holds the name of the current file. And $0 gives the first argument on the command line. For example, if I ran the file with ruby test.rb, $0 = test.rb. If the code above is in the file test.rb, it would run. If I ran the file ruby test2.rb and test2.rb calls the file test.rb, the code above would not run because $0 = test2.rb.

This is a handy trick to run put some tests at the bottom of your file.

Cloudflare

I just put coldandheartless.com on Cloudflare. It sounds like something that would be really helpful and I figured I’d give the free version a try before I move another domain to the paid version. It was incredibly easy to set up, which was great. Took basically a single click in my Badger account to enable Cloudflare and then put in the new dns values. I’ll admit that I don’t exactly know how it all works, but so far it seems pretty cool. I did see that there’s a wordpress plugin for Cloudflare and I’ll probably install that next.

Rails Integration Tests

After unit tests, for me, the important tests are integration tests. This is where I can test logging in and checking authorizations and calculations. They are a bit more involved, but not too difficult once you get the hang of them.

My app authenticates users using ldap. One great advantage I have is that I’m in charge of the ldap system as well. So I just made a couple of ldap users, who were NOT allowed to login to our normal system, and used them to test that logins were working.

Users fixture

# These two accounts have been set up as 
#non login accounts on the server for testing purposes
admin:
  cnetid: admin
  firstname: Admin 
  lastname: User
  role: admin
  rate: 75
  email: [email protected]
  
regular:
  cnetid: regular
  firstname: Regular
  lastname: User
  role: user
  rate: 50
  email: [email protected]

All of my integration tests have a setup and login (private) method.
They look like this:

  def setup
    @admin = users(:admin)
    @regular = users(:regular)
    # Need the without_session_maintenance here or get an error with authlogic
    # "ActionDispatch::ClosedError: Cannot modify cookies because it was closed."
    @admin.save_without_session_maintenance
    @regular.save_without_session_maintenance
    
    @edg1 = projects(:edg1)
    @edg2 = projects(:edg2)
  end

  private
  def login(user, password)
    get "/login"
    post_via_redirect "/user_sessions/create", 
     :user_session => { :cnetid => user, :password => password }
  end

Once I have that setup, I can start writing my tests. Basically, all I do in each test is login with one of my valid users and then run my assertions. As an example, in the following test, I’m logging in as a regular user and then I’m going to try to edit the profile of the admin user. Since I have my authorization rules set so that users (who are not admins) can only edit their own profile, this should not be allowed. If a user does try to edit someone else’s profile, they should be redirected to the root_path.

  test "user trying to edit another user profile" do
    login(:regular, 'password')
    get_via_redirect (edit_user_path(id = @admin.id))
    assert_equal root_path, path, "User allowed to edit another user's profile"
  end

I have a bunch of tests that login as my regular user and my admin and try to edit various things.

A more elaborate integration test is one that calculates expenses for a given project in a given month. That test looks like this:

  test "calculate monthly report" do
    login(:admin, 'password')
    get_via_redirect new_timesheet_path
    timesheet1 = Timesheet.new(:user_id => @regular.id, :monthyear => '2011-10-01', 
                :entries_attributes => {"0" => { :project_id => @atlas.id, :hours => 10 }, 
                                        "1" => { :project_id => @cdf.id, :hours => 20 }})
    assert timesheet1.save, "Didn't save first timesheet"
    
    timesheet2 = Timesheet.new(:user_id => @admin.id, :monthyear => '2011-10-01',
                :entries_attributes => {"0" => {:project_id => @cdf.id, :hours => 100 },
                                        "1" => {:project_id => @atlas.id, :hours => 50 }})
    assert timesheet2.save, "Didn't save second timesheet"
    
    # Add another timesheet in a different month to make sure the calculation is
    # only using ones from the month selected
    timesheet3 = Timesheet.new(:user_id => @regular.id, :monthyear => '2011-11-01',
                :entries_attributes => {"0" => {:project_id => @cdf.id, :hours => 1000 },
                                        "1" => {:project_id => @atlas.id, :hours => 1000 }})
    assert timesheet3.save, "Didn't save third timesheet"
    
    get_via_redirect monthly_report_projects_path(:month => '2011-10-01')
    assert_not_nil assigns(:projects), "@projects is nil"

    assert_select "table" do
      assert_select "tr" do
        assert_select "td", "ATLAS", "no ATLAS line"
        assert_select "td", "123456-6200", "no ATLAS account"
        assert_select "td", "$4,250.00", "wrong ATLAS value"
      end
      assert_select "tr" do
        assert_select "td", "CDF", "no CDF line"
        assert_select "td", "234567-6200", "no CDF account"
        assert_select "td", "$8,500.00", "wrong CDF value"
      end
    end
   

In line 2, I login as my admin user. Then I get a new timesheet. Lines 3-19 are just me generating three timesheets. I made sure that I got timesheets from both users and one from a different month.

Line 21 goes to the monthly_reports page and gets the info for the month starting on 2011-10-01. The assertion in line 22 makes sure that @projects is not empty. Next, I look at the html on the page that was rendered. I’m looking for a table and then a row. In lines 26-28, I’m looking for a td with the name of the project (ATLAS), then a td with the project account-subaccount info. Line 28 has the most important assertion, it’s checking that the total displayed is equal to the value I calculated that the account should be charged for that month, based on the timesheets I entered earlier. Lines 30-34 just repeat the process with the other account number.

Rails Unit/Functional Tests

In my latest rails project, I am trying to write good tests for everything important. My first tests were all unit tests. These are pretty easy. All they basically do is make sure that the data that’s stored in the database is formatted properly. So I have a bunch of tests that make sure that my validations are correct. A sample test looks like this:

  test "save a project without a subaccount" do
    project = Project.new(:name => 'Bit Test', :account => '123432')
    assert !project.save, "Saved a project without a subaccount"
  end

This is pretty basic. What I like about unit tests though are how they make sure a custom validation is working correctly. In this application, I’m tracking costs for a number of projects. Each project has an account and subaccount stored with it. The account-subaccount combination must be unique. So I have a validation in my model like this:

validates_uniqueness_of :account, :scope => [:subaccount]

And I can check this validation with this unit test:

  test "save the same account-subaccount combo twice" do
    project = Project.new(:name => 'NSF', :account => '12345', :subaccount => '1234')
    assert project.save, "Didn't save first account-subaccount combo"
    project2 = Project.new(:name => 'DOE', :account => '12345', :subaccount => '1234')
    assert !project2.save, "Saved an account-subaccount combo twice"
  end

Functional tests check the controller. For this project, everything is behind a login. No one can see anything without logging in. So, the only controller test I can really make is to check that anyone trying to get to a page without logging in is directed to the login page. So I really only have a single functional test for all my controllers.

  test "should not get index" do
    get :index
    assert_response 302, "Didn't get redirected"
    assert_redirected_to login_url, "Didn't go back to login page"
  end

I guess I could write a test for each page (new, edit, show, etc.) behind the login, but I’m satisfied with just checking a single one.