MarkUs Blog

MarkUs Developers Blog About Their Project

Archive for January, 2010

Learnings from my first changelist

without comments

Weird Behaviour of Mocha

In the markus code, there are a lot of places where we use markus_config_<something> instead of MarkusConfigurator.markus_config_<something>. We should start using the latter. He’s why:

ensure_config_helper.rb


def self.check_config()
puts "Checking #{markus_config_logging_logfile}"
puts "Checking #{markus_config_logging_errorlogfile}"
puts "Checking #{markus_config_repository_storage}"
puts "Checking #{markus_config_validate_file}"
puts "Checking #{MarkusConfigurator.markus_config_logging_logfile}"
puts "Checking #{MarkusConfigurator.markus_config_logging_errorlogfile}"
puts "Checking #{MarkusConfigurator.markus_config_repository_storage}"
puts "Checking #{MarkusConfigurator.markus_config_validate_file}"
check_in_writable_dir(markus_config_logging_logfile, "MARKUS_LOGGING_LOGFILE")
check_in_writable_dir(markus_config_logging_errorlogfile, "MARKUS_LOGGING_ERRORLOGFILE")
check_writable(markus_config_repository_storage, "REPOSITORY_STORAGE")
check_readable(markus_config_repository_storage, "REPOSITORY_STORAGE")
if ! RUBY_PLATFORM =~ /(:?mswin|mingw)/ # should match for Windows only
check_executable(markus_config_validate_file, "VALIDATE_FILE")
end
end

Output from running rake test:units When loading everything up:


Checking log/info_development.log
Checking log/error_development.log
Checking /home/jmate/everything/workspaces/repos
Checking /home/jmate/everything/workspaces/markus/config/dummy_validate.sh
Checking log/info_development.log
Checking log/error_development.log
Checking /home/jmate/everything/workspaces/repos
Checking /home/jmate/everything/workspaces/markus/config/dummy_validate.sh

At this point, <blah> == MarkusConfigurator.<blah>

When running the test cases:


/tmp/ensure_config_helper_test_777699315/log/log_info_file.log
Checking log/info_test.log
Checking log/error_test.log
Checking /home/jmate/everything/workspaces/repos
Checking /home/jmate/everything/workspaces/markus/config/dummy_validate.sh
Checking /tmp/ensure_config_helper_test_777699315/log/log_info_file.log
Checking /tmp/ensure_config_helper_test_777699315/log/log_error_file.log
Checking /tmp/ensure_config_helper_test_777699315/source_repo_dir
Checking /tmp/ensure_config_helper_test_777699315/validate_script.sh
/tmp/ensure_config_helper_test_595310852/log/log_info_file.log
...
...
...
Checking log/info_test.log
Checking log/error_test.log
Checking /home/jmate/everything/workspaces/repos
Checking /home/jmate/everything/workspaces/markus/config/dummy_validate.sh
Checking /tmp/ensure_config_helper_test_473533902/log/log_info_file.log
Checking /tmp/ensure_config_helper_test_473533902/log/log_error_file.log
Checking /tmp/ensure_config_helper_test_473533902/source_repo_dir
Checking /tmp/ensure_config_helper_test_473533902/validate_script.sh

Now you can see that <blah> != MarkusConfigurator.<blah> . So the namespace for the method you are trying to call cannot be ambiguous. In the source code above you must use MarkusConfigurator.<blah>.

Mocking Modules with Mocha

I could not find any examples on mocking modules with mocha. It’s probably because it’s so easy! It’s just like mocking an instance of a class.

the_module.rb :


module TheModule
def the_module_function
return "the real value"
end
end

test.rb :


require "test/unit"
require "mocha"
require "the_module"
include TheModule

class TheModuleTest < Test::Unit::TestCase
# replace 'the real value' with 'the mocked value'"
def test_it
assert TheModule.the_module_function == "the real value"

TheModule.stubs(:the_module_function).returns("the mocked value")

assert TheModule.the_module_function == "the mocked value"
end
end

Running the tests:


jmate@CalculatorJozef:~/everything/workspaces$ ruby test.rb
Loaded suite test
Started
.
Finished in 0.00096 seconds.

1 tests, 2 assertions, 0 failures, 0 errors

Nested Contexts

I learned a new trick with shoulda. Credit goes to: http://www.viget.com/extend/reusing-contexts-in-shoulda-with-context-macros/

You can nest contexts inorder to resuse them.

Here is a quick example I prepared:


context "we have a temp dir" do
setup do
@temp_dir = "/tmp/temp_#{rand(1073741824)}"</pre>
@log_dir = "#{@temp_dir}/log"
@file = "#{@log_dir}/file"
FileUtils.mkdir( @temp_dir )
end
teardown do
FileUtils.rm_r( @temp_dir )
end
should "be able to test with the temp dir" do
end

context "we have a log dir" do
setup do
FileUtils.mkdir( @log_dir )
end
should "be able to test with the temp and log dir" do
end

context "we have a file inside the log dir inside the temp dir" do
setup do
FileUtils.touch( [@file] )
end
should "be able to test with temp, log and file" do
end
end
end
end

Permissions, Directories and Ruby

I recently learned that if you remove the execute bit on a directory and try to rm -r the parent directory then you will be unable to remove the executable directory. However, this works in a terminal.

Example in ruby:


#!/usr/bin/env ruby
require 'fileutils'
include FileUtils

@parent_dir = "/tmp/parent_#{rand(1073741824)}"
@test_dir = "#{@parent_dir}/test"
@file = "#{@test_dir}/file"

FileUtils.mkdir( @parent_dir )
FileUtils.mkdir( @test_dir )
FileUtils.touch([ @file ])
FileUtils.chmod( 0600, [ @test_dir ])
FileUtils.rm_r( @parent_dir )

Output from script:


jmate@CalculatorJozef:~/everything$ ./test.rb
/usr/lib/ruby/1.8/fileutils.rb:1297:in `unlink': Permission denied - /tmp/parent_674314876/test/file (Errno::EACCES)
from /usr/lib/ruby/1.8/fileutils.rb:1297:in `remove_file'
from /usr/lib/ruby/1.8/fileutils.rb:1302:in `platform_support'
from /usr/lib/ruby/1.8/fileutils.rb:1296:in `remove_file'
from /usr/lib/ruby/1.8/fileutils.rb:1285:in `remove'
from /usr/lib/ruby/1.8/fileutils.rb:756:in `remove_entry'
from /usr/lib/ruby/1.8/fileutils.rb:1335:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:1335:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:1339:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:1334:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:1333:in `each'
from /usr/lib/ruby/1.8/fileutils.rb:1333:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:1334:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:1333:in `each'
from /usr/lib/ruby/1.8/fileutils.rb:1333:in `postorder_traverse'
from /usr/lib/ruby/1.8/fileutils.rb:754:in `remove_entry'
from /usr/lib/ruby/1.8/fileutils.rb:612:in `rm_r'
from /usr/lib/ruby/1.8/fileutils.rb:608:in `each'
from /usr/lib/ruby/1.8/fileutils.rb:608:in `rm_r'
from ./test.rb:14

Example in terminal:


jmate@CalculatorJozef:/tmp$ mkdir parent
jmate@CalculatorJozef:/tmp$ mkdir parent/test
jmate@CalculatorJozef:/tmp$ touch parent/test/file
jmate@CalculatorJozef:/tmp$ rm -r parent

As you can see from the output above. I had no trouble doing this in the terminal.

It might have something to do with not being able to cd into a directory that does not have the execute bit set.

I hope the knowledge I pass on helps you guys:

Ruby Permissions and Directories

Nested Contexts

Mocking Modules with Mocha

Weird Behaviour With Mocha

Cheers,
Joseph

Written by jmate

January 30th, 2010 at 11:14 pm

Posted in Getting Started

Meeting Minutes – Jan. 29, 2010

with one comment

The meeting started at 3:30 and ended at 4:28.

The IRC log can be found here

Agenda

  • Feedback from users
  • Round table
  • Other issues

Feedback from users

  • We’ve been getting great feedback so far!
  • Karen has been keeping us posted through the mailing list

Round table

  • We had a pretty big group today, including our friends from France!
  • Nelle has been working on implementing sections and adding students to sections. She has a couple of UI issues right now. Nelle is going to try and stay in touch with Victoria to make sure they’re not working on conflicting things. Nelle has also been looking into moving over to Machinist.
  • Benjamin is working on translating MarkUs into French.
  • Farah has been working on unit tests for the grades tables (and fixing some bugs related to the table as well).
  • Brian worked on unit tests for Ticket #570.
  • Robert has been busy with interviews this week.
  • Bryan worked on Ticket #393 and is now working on tests.
  • Joseph has been working on Ticket #574. We decided to put a comment in the setup file that explains why quotes around the path are necessary and then check whether or not the validate program runs.

Other issues

  • Karen would like to see descriptions of tickets in our punchlines (instead of just the ticket numbers)
  • The French team will be posting reports here every couple of weeks
  • We are looking for students for an NSERC USRA for the summer
  • Victoria is going to be creating a blog post about the wireframes she has created so far for TA assignment

Written by Farah Juma

January 29th, 2010 at 6:09 pm

Posted in Meetings,Minutes

Assign Graders View — Prototypes

with 4 comments

I’ll be writing a follow-up post for these wireframes.  But for now, please feel free to take a look and leave some comments/feedback!

Read-Only Mode — which we will most likely no longer have:

Overview: UI that allows user to view existing grader-to-group assignments.

Overview: UI that allows user to view existing grader-to-group assignments.

Edit Mode — will be the new default UI when user opens up the Assign Graders tab:

Assign Groups: UI users will use to create/modify grader-to-group assignments.

Assign Groups: UI users will use to create/modify grader-to-group assignments.

Assign Groups: Example of user interaction in edit mode.

Assign Groups: Example of user interaction in edit mode.

That’s all for now! 😀

Written by Victoria

January 29th, 2010 at 5:51 pm

Posted in User Interface

January 28th Status Update

with one comment

Mike

Status

  • Fixed the functional tests!  Yeah!
  • Put the functional tests on markusproject.org homepage – though they act funny in an “off and on” sort of way…
  • Reviewed some code
  • Closed #530 (next/prev submission links in grader view no longer skip completed assignments in 0.6 – needs to be pushed to trunk)
  • Wrote a blog post about closing #531:  http://blog.markusproject.org/?p=1103


Next Steps

  • Review more code as it comes in
  • Turn the rest of Byron’s email into tickets (can’t believe I haven’t finished that yet)
  • Take a look at some other high-priority fixes maybe to patch 0.6
  • Brace myself for possible MarkUs support…CSC148 and CSC209 assignments due tomorrow.


Roadblocks

  • This is a heavy week and a half for me – that’s why I did most of my work over the weekend.  Might not respond to email this weekend, and will be pretty bogged down until next Wednesday sometime.

Brian

Status

  • 1 post on Markus blog
  • Finished #570 units test cases, change committed


Next Steps

  • Fix some bugs on weekends .


Roadblocks

  • Job hunting, 1 graduate course that requires intensive reading of papers, 1 research project

Victoria

Status

  • Completed first set of wireframes for the Assign Graders View.
  • Got useful feedback from Karen and Farah during last night’s UI meeting.

Next Steps

  • Start prototyping for the Group tab.  That is, the view users use to create new groups and modify existing groups.
  • Summarize new usability issues and ideas from last night’s UI meeting and write a blog post about it.

Roadblocks

  • Learning how to use a new application for prototyping.  I’m slowly getting the hang of it! 🙂

Joseph

Status

  • handling validate files with a space and checking configuration on startup is on reviewboard
  • ticketed the paging bug where the page number and page size are not saved in a bookmark or when hitting back/forwards
  • did rudimentary research on will_paginate – have not found anything so far

Next Steps

  • finish up the codereview
  • complete research on will_paginate
  • conclude which method to approach the pagination problem after research is complete

Roadblocks

Bryan

Status

  • Working on #393, Reviewing code, learning Ruby and Shoulda.


Next Steps

  • Solve more tickets.


Roadblocks

  • Not enough knowledge of Ruby, testing, and Markus’ structure.

Nelle

Status

  • Work on implementing creating section and to adding students to them
  • Started to look on how to migrate smoothly to Machinist


Next steps

  • Implementing the group members from same section limitation
  • Improving the UI on the different parts implemented this week


Roadblocks

  • None

Robert

Status

  • Working on tests for my fix for 510, otherwise Halted.
  • Reviewed changes from team members as they come in.

Next Steps

  • Find time to work on MarkUs.

Roadblocks

  • Many consecutive interviews [Google, Microsoft, Amazon, Facebook], midterms, and assignments all at once.

Farah

Status

  • Fixed a bug related to alphabetical pagination which was causing the alphabetical categories to get re-calculated each time the user switched between pages instead of only when the number of items per page is changed (and learned about session variables)
  • Re-factored code to make the GradeEntryFormsController lighter by moving some things to the model instead
  • Finished the unit tests for the grades table
  • Dropped in on the UI meeting on Wednesday

Next Steps

  • Finish functional tests for the grades table
  • Student interface for grade entry forms

Roadblocks

  • None this week

Written by Robert B

January 28th, 2010 at 8:58 pm

Posted in Uncategorized

Re-factoring contexts with Shoulda

with one comment

I’ve been playing around with Ruby on Rails for a personal project that I started in December and as we starting doing with MarkUs, I’ve been using Shoulda for my tests. One of the basic tenets of Ruby on Rails is DRY – Don’t Repeat Yourself. And I’ve often found that with Shoulda tests, I was writing the same code over and over again. I’ve had some difficulties scoping the internet for ways to re-factor Shoulda tests, but I’ve come up with two useful ways so far that I thought I would share with you. Perhaps this is just my still naivety with Ruby on Rails, but since most of us are in a similar boat, I thought I’d share my findings.

1. Class methods

This works great if your setup varies significantly between tests of a method, but you still want almost the same thing (or the exact same thing) to happen in each of the cases. You can create class methods in test class to re-factor tests like this. The key part is that you define the method prior to the highest-nested level context of any test that will use the method. I like naming them starting with should_ to clearly indicate what they’re for 🙂

def self.should_flip_active
  # Put your should statements here, including should "..." do ... end and should_*
end

2. Iterating over a set of test data

With unit tests, we shouldn’t really be using fixtures and loading everything from the database. Instead, you might just set up the few attributes that you need on a model instance to test a method on it. If you want to do this for slightly different data, then you can use either a hash or an array and make a context for each of them!

Structure with an array:

['c6conley', 'g9merika'].each do |user|
  context "with user "+user do
    # Put your setup and should statements in here - you could even make it nested further!
  end
end

Structure with a hash:

{ 'c6conley' => 5, 'g9merika' => 8 }.each do |user, section|
  context "with user "+user do
    # Do some tests on user with section
end

One last comment on Shoulda – I’ve found that you can only access assigns, e.g. assigns(:student).some_student_attribute from within should blocks. I’ve run into some problems when running my tests if I try to use assigns or a class variable like @student within an open area in a should statement. Here’s some examples:

should "work" do
  assert_equal 'hello', assigns(:student).user_name
end

# should not work
should_set_the_flash_to assigns(:student).user_name

should "work" do
  assert_contains flash.values, assigns(:student).user_name
end

Happy Shoulda testing!

Written by Tara Clark

January 26th, 2010 at 6:10 am

Posted in Automated Testing

Notes system: what’s left to do

with one comment

This post was originally written at the beginning of December 2009 and I just found it now, so I’m publishing it 🙂

Our original steps for the Notes system implementation went as follows:

  1. Design the model.
  2. Create mock-ups of the user interface.
  3. In parallel, design the Notes tab and the modal dialog interfaces (for groupings).
  4. Extend this functionality to assignments and to students once the notes system is solid for groupings.

We have completed the first three steps, including unit and functional tests. Thanks to the polymorphic, “noteable” idea that we used for the relationship between a note and a grouping, the only work necessary to have notes on a different object type is to:

  • add a “display_for_note” method to the model, like we did for groupings – this allows us to display these notes
  • modify the create a note form in the Notes tab to allow for other types of noteable objects than just groupings
  • add a link to the modal dialog in an appropriate location for the object type

For now, I can’t see the best place to place a link to a modal dialog to create a note associated to an assignment or to a student, so I would recommend just adding that functionality to the Notes tab.

Written by Tara Clark

January 26th, 2010 at 5:41 am

Posted in Notes System

Removing Marks

with 6 comments

Right now, MarkUs lets graders choose a mark from 0 – 4 to assign to a particular criterion on the rubric.  However, MarkUs does not currently allow graders to remove those marks once they’ve been made.  They can change the level, but they can’t flat out remove it.  This problem is filed as ticket #531.

My approach is to simply add a link that allows graders to remove the mark.  Simple as that.  I’ve thrown together a quick and dirty UI mockup – see below:

Remove that mark!

Remove that mark!

It really might be that quick and easy.  In fact, this problem might be ripe for one of my new teammates to sharpen their teeth on. It’ll be a good experience working with RJS, the Rails AJAX helpers, and the Grader View (which is one of my favourite parts of the entire app).  So I’m going to assign this ticket to “nobody”, and see who bites (and who’s reading the blog!).  😀

Written by m_conley

January 25th, 2010 at 5:58 pm

Posted in Uncategorized

Sections: specifications & ideas

with 5 comments

One of the functionality we would like to implement this semester is section management.

Here is the content of this post

Details specifications

  • Group management : the groups should be formed of two or three students of the same section ;
    • instructors need to be able to add the students section through the web interface or via the CSV file upload.
    • the student list should have filter to sort students per section.
    • instructors should be able to switch from two modes, in the assignment property tab:
      • groups have to be formed with students from the same section.
      • groups DO NOT have to be formed with students from the same section.
    • when switching to this mode, the application should display a warning message if some of the students don’t have a section associated to them.
    • students should see whether the groups have to be formed of students in the same section or not.
    • when the mode is activated, inviters should not be able to invited students in another section than theirs.
    • if some students don’t have a section, inviters with no section will be able to invited only students without any sections.
  • Deadlines : Each section needs to be associated with one specific deadline ;
    • this functionality can be enabled only if groups are limited to same-section students.
    • when enable, instructors can specify one deadline per section in the assignment property view.

If deadlines are specified per sections, it is logical that submissions rules could be too. For the first implementation, we will disable submission rules.

Database schema

section_db_schema

Sections table

This table is used to save all the sections. In the case of UofT, it should be from 2 to 3 sections. For Centrale Nantes (a French engineer school), 12 sections (groups).

id: int
name: string

Users table

We added a foreign key to sections. This is mostly used for students, but can also be used for Graders (we could then map graders to groups per sections).

Assignments table

There are a lot of options that can be added with the new section scheme.

section_due_dates: boolean, false
section_groups: boolean, false
section_submission_rules: boolean, false

Section_due_dates table

This links assignments and section, to add a specific due date to each section for an assignment.

id: int
section_id: int, fk
assignment_id: int, fk
due_date: date

If you have any thought, please chime in !

Written by nvaroqua

January 25th, 2010 at 10:08 am

Sharing some newbie’s experience, =P

with 2 comments

In last week, I fixed the bug #570. Although this bug is not a difficult one, I do learn a lot in the process fixing it. I would like to share some experience of it. My route may not be as efficient as yours, please feel free to advice a better way. I need you guys’ suggestion to improve my skills,=P.

Firstly, I used the following way to find the place to start. For example, in the #570, the problem is the string not being stripped. Without much knowledge about the project structure, I just ran the project, opened the firefox with firebug running, and then find the string name “user_name” in the table on the page of adding user. After I got the string name I made a search in the project of “user_name” which returned quite a lot of results. Then I started to browse those results to find target methods like “create”, ”add”, “update” etc. I did find these methods in “/controllers/students_controller.rb” which use the parameter params[:user] to create the new student records.

At first glance this seemed to be the place to modify the string, and I modified the string here, which did work when I did some manual tests. However, I noticed that there are at least 3 controllers of “student”, ”ta” and “admin” that use very similar methods. If I applied the rough ideas I will need to modify at least 3 places that will potentially bring difficulty of maintenance in future. Then I started to think about finding the original place of this user object. Some places that I suppose things like the string validation would happen. When I noticed that there is a User class that are inherited by “student”, ”ta” and “admin”, I knew this is the right place to do the job.

However, I didn’t know how to do this due to my lack of knowledge of Rails. Well, here I learned how to save your time by asking your team members who know the projects well and are willing to help,=). Just asked a quick question to Mike and he pointed out that there are some callbacks in ActiveRecord that we can use to validate the variables at different states. Then I started to search the web and figured out how to use it. A new method was added to User class to trip all the input strings. At this point I have already solved half of the problem. It was exciting to me!

The next step will be adding test cases for this new method. Again, communication is really important and I learned how to write the test cases from Mike. Here are some rough steps I did for my tests:

  1. Make sure you have no error and no failure before your modification to the project.
  2. Find the unit test under test/unit. There is usually a name matching from the test case to the tested class. For example I found the “user_test.rb” test “user.rb”.
  3. I have no idea how to write the test cases at first. I talked to Mike and also took a look at existing test cases. As suggested, we shall use shoulda to test because it is better for reading. For me, I didn’t really search tutorials of shoulda on the web. I just found some existing codes in our project and figured out the basic structure is like:

context “some one” do

  1. setup do
  2. end
  3. should “do something” do
  4. assert something
  5. end
  6. end

Basically “setup do” is the place to put the setup of your test values. And “should” is the place to add the function you perform like user. save, and tests you add like assert, assert_nil, assert_equal. You can add multiple shoulds within a context.

When your run the test by typing ruby -Itest test/unit/sometest.rb, it will give the result like “some one do something <false> is not true “when your test case fails.

4. I suggest after you pass the single test that you modified, run a full tests (rake test:units) to make sure you pass all the rest tests as well.

Check our last irc meeting log, you will find some useful tips about testing.

Above are some thoughts I come up with my experience of solving #570. I hope it suggest some useful points. If you get confused at some points, please let me know. I would try to explain. And I am also willing to hear  from you guys,=).

Written by Brian Xu

January 24th, 2010 at 8:34 pm

Meeting Minutes: Jan. 22nd, 2010

with one comment

The meeting started at 3:31 and ended at 4:16.

The IRC log can be found here.

Agenda

  • Byron’s Email
  • Initial round table
  • Best Practices

Byron’s Email

  • It provided us with many bugs and usability aspects to look at.
  • He’s also happy with MarkUs so far. (Yay!)

Initial round table

  • Not much was done. Recovering from Code Sprint. That’s OK.
  • Joseph: looking into the paginate/back issue with the Submissions table
  • Brian: Working on 570

Best Practices

  • Start off with smaller bugs to learn the system better.
  • Don’t overwhelm yourself. Do a bit at a time and ask for help if you need it.
  • MarkUs tends to work in 2 week iterations.  Assign bugs to those deadline’s appropriately.
  • Post Sneak Peaks on Review Board to get input on works in progress. Especially for big changes!
  • Do anything remotely interesting? Blog it!
  • Learn something cool? Blog it!
  • Blog blog blog! Communication is important.

Written by Robert B

January 22nd, 2010 at 9:16 pm

Posted in Meetings,Minutes