CSC/ECE 517 Fall 2018/E1853 Write unit tests for menu.rb

From Expertiza_Wiki
Revision as of 21:17, 2 November 2018 by Bbryson (talk | contribs) (→‎Results)
Jump to navigation Jump to search

This project wrote unit tests for the Menu.rb model in Expertiza.

Project Introduction

The menu model is used to create the top bar menu in expertiza. It does this by obtaining and organizing Menu_Items based on the current users Role. Before this project there were no unit tests for menu.rb. This project seeked to bring the unit test coverage above %90.


Team

Barrett Bryson (bbryson)

Komal Kangutkar (kmkangut)

RSpec File

The final result can be found at expertiza/spec/models/menu_spec.rb. This specific test can be run by calling in the expertiza directory:

  rspec -fd ./spec/models/menu_spec.rb

The addition of the -fd argument will write out full descriptions of the tests and provide a easy look at the work we did.

Design

In total we wrote 29 tests that covered all of the functions in both menu and its internal node class. We created 6 menu items for testing using the given factories as well as 1 role used to test the menu constructor. We stubbed menu item to always return an array of the 6 test items that we created. Other pieces of the code were stubbed because these pieces should be tested by menu item not menu. The double temp is used to only test the functionalities of menu.

Each method in menu.rb has at least two tests checking both a know success case and a edge case or potential failure. As an example, a detailed look at the functions to test menu#initialize is found below.

  context "when role is nil" do
    it "creates a new menu" do
      menu = Menu.new
      expect(menu.instance_of?(Menu))
    end
  end

This first test revealed an error in the existing menu.rb code in the line shown below. The second line shows the change that we made. This allowed the code to be more robust and prevent noMethodErrors from nilClass. Without this change a menu created with a nil role will throw an error causing the program to fail unnecessarily. This is important because the default value of role is nil and that should not fail.

  items = MenuItem.items_for_permissions(role.try(:cache)[:credentials].try(:permission_ids))
  items = MenuItem.items_for_permissions(role.try(:cache).try(:[], :credentials).try(:permission_ids))

The second test uses the main covers the main use case of menu. It will be supplied with a role and will assemble a menu. Only a single role is tested because further testing of roles and menus should instead be handled in integration tests.

    context "when a role is passed as an argument" do
      it "creates a new menu" do
        admin_role = build(:role_of_administrator, id: 3, name: "Administrator", description: '', parent_id: nil, default_page_id: nil)
        menu = Menu.new(admin_role)
        expect(menu.instance_of?(Menu))
      end
    end

The third test checks that when the menu is created with items, these items are put into nodes and contained within the menu. In this case the children of root will contain a single item, the node with id 1, because this node has a nil parent. The other nodes all have parents.

    context "when menu has items" do
      it "creates a new menu with items" do
        menu = Menu.new
        expect(menu.root.children.length).to eq(1)
      end
    end

The final test checks a menu without any nodes. While this case is unlikely in actual use it is important it can be handled without throwing any errors. When a menu without any items is created, the root will never have anything added to its children array so this array will be nil.

    context "when menu has not items" do
      it "creates a new menu without items" do
        allow(MenuItem).to receive(:items_for_permissions).with(anything).and_return([])
        menu = Menu.new
        expect(menu.root.children).to be_nil
      end
    end

This 4 tests alone provide nearly 85% coverage of menu.rb because of how much they rely on a variety of other methods within the class.

Many of the functions in menu return a menu node. The simplest, get_item, takes the node id and returns the node object. All following functions use this to test that the correct node is returned. However to prevent circular logic, the get_item test only checks the id of the returned node.

Results

The 29 tests provide 100% coverage of the lines in menu.rb. A video of all tests running can be seen here.

The main repository can be found here

The forked git repository for this project can be found here

List of all tests

Below is a list of the descriptions of all of the tests we wrote