E1853 Menu Model Testing: Difference between revisions
No edit summary |
|||
(18 intermediate revisions by the same user not shown) | |||
Line 47: | Line 47: | ||
==Problem Statement== | ==Problem Statement== | ||
The goal of the project is to test the Menu.rb, i.e. the Menu model by writing unit tests, which are written using [http://rspec.info/ Rspec]. The unit tests are to be written such that the path coverage of menu.rb is greater than 90% and achieve the highest possible branch coverage. | The goal of the project is to test the Menu.rb, i.e. the Menu model by writing unit tests, which are written using [http://rspec.info/ Rspec]. The unit tests are to be written such that the path coverage of menu.rb is greater than 90% and achieve the highest possible branch coverage. | ||
===Files Involved=== | ===Files Involved=== | ||
The following files were involved: | The following files were involved: | ||
# app/models/menu.rb (already existing) | # app/models/menu.rb (already existing) | ||
# spec/models/menu_spec.rb(created as part of this project) | # spec/models/menu_spec.rb(created as part of this project) | ||
===Team Members=== | ===Team Members=== | ||
The members involved in the project include : | The members involved in the project include : | ||
# Ameya Dhavalikar(student) | # Ameya Dhavalikar(student) | ||
# Hasham Mukhtar(student) | # Hasham Mukhtar(student) | ||
# Mingkang Zhuang | # Mingkang Zhuang(student) | ||
# Zhewei Hu(mentor) | # Zhewei Hu(mentor) | ||
==Plan of Work== | |||
==Plan of Work - Test Plan== | |||
The goal is to test the menu model file. For this, we create a corresponding menu_spec.rb file where we write the tests. | |||
For this purposes different sub-tasks involved: | |||
1. Setting up the Expertiza environment | |||
2. Understand the functionality of model file in menu.rb | |||
3. Understand the linked data attributes being used, like menu_items, controller_actions, content_page, permissions_id, etc. | |||
4. Creating dummy entries for testing different functionalities. | |||
5. Writing testing conditions for different functions and cross-checking with the expected outputs. | |||
==Implementation== | ==Implementation== | ||
===Expertiza | |||
=== Expertiza Environment Setup === | |||
The steps that we followed to set up the Expertiza environment are as follows: | |||
# Install Virtual Box software from Oracle in the local machine. | |||
# Download the Ubuntu image and import the image file into the Virtualbox environment. | |||
# Execute the following set up commands in the terminal to set up the application in the local machine. | |||
Setup commands: | |||
*sudo su | |||
*gem install bundler | |||
*exit | |||
*git clone [Forked Expertiza repository url] | |||
*cd expertiza | |||
*bash setup.sh | |||
(change config/database.yml, there is no MySQL password by default) | |||
*bundle install | |||
*rails server | |||
After successfully setting up the environment, LogIn to the Expertiza application using necessary credentials. | |||
To navigate to the menu.rb file: | |||
1. Open terminal inside the virtual environment. | |||
2. Navigate to the model folder of the application by typing the following command in the terminal: | |||
<b>cd/expertiza/spec/models</b> | |||
===Functionality of Menu model=== | ===Functionality of Menu model=== | ||
Menu is a model which gives the functionality to the top menu bar in the Expertiza website. It controls the display of the tabs based pn the user. It links the menu items associated with each tab in the menu using a tree. It directs how these tabs are displayed with regards to different users which have different permission attributes. | |||
A super admin has the permission to edit the menu bar, by adding or deleting menu item blocks from it. Upon adding each item, he gets to position it either in the main menu bar or into different subcategories. | |||
===Sample Views=== | |||
The following Menu is displayed for the Student role : | |||
[[File:Menu Student View.png]] | |||
===Test entries creation=== | ===Test entries creation=== | ||
=== | Mock/dummy objects are needed to be created for any unit testing criteria. These objects are loaded newly and deleted after every testing condition. | ||
== | |||
Several methods exist for creating such objects, whose parameters need to be designed to satisfy the conditions under test. Using factories command pattern is one such method where few of the attributes are filled in with predefined values when created. | |||
We have used factories and created the mock objects that we need to execute the tests. Menu model require several other mock objects to be created namely Node(this is a subclass in the menu class), menu_item, site_controller, controller_action,etc. | |||
===Conditions tested in Menu=== | |||
A total of 21 testing conditions were required to be performed for testing all the functions in menu model file. | |||
The conditions that needed to be tested are as below: | |||
Node class | |||
1. initialize | |||
In this method, we check whether the parent attribute of the node instance passed is set to nil. We have therefore written a test in which | |||
the expectation of the test is that the parent attribute of the node instance is Nil. | |||
2. setup | |||
2.1 In this scenario, the controller_action attribute of the menu item is nil. In this case, the expectation is that the content page path of | |||
the current menu item is assigned to the URL variable. | |||
2.2 In this scenario, the controller_action attribute of the menu item is not nil. In this case, the expectation is that the URL of | |||
controller_action is assigned to the URL variable. | |||
2.3 In this scenario, the controller_action attribute of the menu item is unavailable. In this case, the expectation is that a customised path | |||
is assigned to the URL variable. | |||
3. site_controller | |||
3.1 In this scenario, the site_controller variable is nil. In this case, the expectation is that the site_controller is found by the | |||
id and returned. | |||
3.2 In this scenario, the site_controller variable is not nil. In this case, the expectation is that the site_controller variable is returned. | |||
4. controller_action | |||
4.1 In this scenario, the controller_action variable is nil. In this case, the expectation is that the controller_action is found by the | |||
id and returned. | |||
4.2 In this scenario, the controller_action variable is not nil. In this case, the expectation is that the controller_action variable is | |||
returned. | |||
5. content_page | |||
In this scenario, the content_page variable is nil. In this case, the expectation is that the content_page variable is found by id and | |||
returned. | |||
6. add_child | |||
In this scenario, a node is added to the @children list. The expectation is that the current node is added to the @children list and the | |||
total number of children are returned. | |||
Menu class | |||
# initialize | |||
1.1 In this scenario, the menu items are nil or empty. The expectation is that the later initialization is terminated and nil is returned. | |||
1.2 In this scenario, the menu items are not nil or empty and the parent id of the node is nil. The expectation is that a hash of menu items | |||
is built by name and id and the current node is made a child node of the root node. | |||
1.3 In this scenario, the menu items are not nil or empty and the parent id of the node is not nil. The expectation is that a hash of menu | |||
items is built by name and id and the current node is made a child node of its parent node. | |||
2. select | |||
2.1 In this scenario, the by_name hash does not contain the given node name. The expectation is that nil is returned. | |||
2.2 In this scenario, the by_name hash contains the given node name. The expectation is that the menu item for the given name is selected. | |||
3. get_item | |||
In this scenario, the menu item id is passed as a parameter to the method. The expectation is that the menu item is returned by id. | |||
4. get_menu | |||
In this scenario, the menu level is passed as a parameter to the method. The expectation is that an array of all the child nodes at that | |||
given level is returned. | |||
5. selected | |||
In this scenario, the expectation is that the name of the currently selected element is returned. | |||
6. selected? | |||
6.1 In this scenario, @selected hash contains menu_id. The expectation is that true is returned. | |||
6.2 In this scenario, @selected hash does not contain menu_id. The expectation is that false is returned. | |||
7. crumbs | |||
In this scenario, the expectation is that a list of menu items is returned based on the contents in the crumbs array. | |||
==Test Results and Coverage== | |||
A screenshot of the tests passing is shown here: | |||
[[File:Rspec Test Passing.JPG]] | |||
===Coverage Results=== | |||
[[File:Coverage.jpg]] | |||
[http://www.youtube.com/watch?v=ymmKTPwBOQQ Link to screencast] | |||
==Conclusion and Learning Outcomes== | ==Conclusion and Learning Outcomes== | ||
After writing the test cases we used SimpleCov to measure the C0 coverage of our rails application. SimpleCov was already installed earlier. | After writing the test cases we used SimpleCov to measure the C0 coverage of our rails application. SimpleCov was already installed earlier. | ||
After running rake spec to run the test cases, SimpleCov creates a directory called coverage in our rails application folder. | After running rake spec to run the test cases, SimpleCov creates a directory called coverage in our rails application folder. | ||
This folder called coverage contains an index.html file which when opened in a browser renders an | This folder called coverage contains an index.html file which when opened in a browser renders an HTML page which gives the C0 coverage of each of the files in the Controllers, Models, Helpers in the app directory. | ||
These are the learning outcomes after performing this project: | These are the learning outcomes after performing this project: | ||
# Writing tests using the Test Driven Development approach. | |||
# Writing unit tests for models and controllers in RSpec. | |||
# Understanding the functionality of an already developed application. In our case, before writing the test cases for the menu.rb we had the understand how different models interacted with each other and how each action by different users would make changes in the database schema. | |||
# An understanding of how different tables are structures in the schema in large applications. | |||
==References== | ==References== |
Latest revision as of 02:08, 3 November 2018
CSC-517 Fall 2018 - E1853 Testing the Menu Model in Expertiza Project. This Wiki page explains how tests were performed for the Menu Model of the Expertiza project.
Introduction
Expertiza
Expertiza is an Open Source project based on the Ruby on Rails framework, supported by National Science Foundation. It is the software to create reusable learning objects through peer review. It is a project where students can submit and peer review learning objects(articles, code, websites, etc). The users of this software include students and professors. Expertiza is used by select professors and students in North Carolina State University, for example. It supports team projects, reviews of projects/teammates, submission URLs, Wiki pages and certain document types. Instructors can create projects and the students can bid for the projects. The students can be assigned teams for a particular project or they may form their own team with fellow classmates.
Test Driven Development
Test Driven Development is a software development process that relies on the repetition of a very short development cycle, requirements are turned into very specific test cases, then the software is improved to pass the new test cases only. This is opposed to software development that allows software to be added that is not proven to meet requirements. Test-driven development is related to the test-first programming concepts of extreme programming, begun in 1999,but more recently has created more general interest in its own right.
The TDD sequence can be can be summarized in following steps:
- Add a Test
- Run all tests and see if the new test fails
- Write the code
- Run tests
- Refactor code
- Repeat
Advantages of using TDD:
- Narrowing Problem Focus
- Tidier Code
- Not worrying about dependencies
- Easier refactoring
- Better Test coverage and fewer bugs
Unit Testing
Unit Testing is a software testing method by which individual units of source code are tested to catch errors early in the development process. For a model it involves testing the interface and on how it responds to commands and queries from outside. Model testing is bounded to the functionality of only the model under test and doesn't test how its collaborating models get affected based on this query.
Unit Testing provides several benefits which can be summarized in the below points.
1. Finds problems early: Unit testing finds problems early in the development cycle. This includes both bugs in the programmer's implementation and flaws or missing parts of the specification for the unit. In test-driven development (TDD), which is frequently used in both extreme programming and scrum, unit tests are created before the code itself is written. When the tests pass, that code is considered complete.
2. Facilitates change: Unit testing allows the programmer to refactor code or upgrade system libraries at a later date, and make sure the module still works correctly (e.g., in regression testing). The procedure is to write test cases for all functions and methods so that whenever a change causes a fault, it can be quickly identified. Unit tests detect changes which may break a design contract.
3. Simplifies Integration: Unit testing may reduce uncertainty in the units themselves and can be used in a bottom-up testing style approach. By testing the parts of a program first and then testing the sum of its parts, integration testing becomes much easier.
4. Documentation: Developers looking to learn what functionality is provided by a unit, and how to use it, can look at the unit tests to gain a basic understanding of the unit's interface's API.
5. Design: When software is developed using a test-driven approach, the combination of writing the unit test to specify the interface plus the refactoring activities performed after the test is passing, may take the place of formal design. Each unit test can be seen as a design element specifying classes, methods, and observable behavior.
Problem Statement
The goal of the project is to test the Menu.rb, i.e. the Menu model by writing unit tests, which are written using Rspec. The unit tests are to be written such that the path coverage of menu.rb is greater than 90% and achieve the highest possible branch coverage.
Files Involved
The following files were involved:
- app/models/menu.rb (already existing)
- spec/models/menu_spec.rb(created as part of this project)
Team Members
The members involved in the project include :
- Ameya Dhavalikar(student)
- Hasham Mukhtar(student)
- Mingkang Zhuang(student)
- Zhewei Hu(mentor)
Plan of Work - Test Plan
The goal is to test the menu model file. For this, we create a corresponding menu_spec.rb file where we write the tests.
For this purposes different sub-tasks involved:
1. Setting up the Expertiza environment
2. Understand the functionality of model file in menu.rb
3. Understand the linked data attributes being used, like menu_items, controller_actions, content_page, permissions_id, etc.
4. Creating dummy entries for testing different functionalities.
5. Writing testing conditions for different functions and cross-checking with the expected outputs.
Implementation
Expertiza Environment Setup
The steps that we followed to set up the Expertiza environment are as follows:
- Install Virtual Box software from Oracle in the local machine.
- Download the Ubuntu image and import the image file into the Virtualbox environment.
- Execute the following set up commands in the terminal to set up the application in the local machine.
Setup commands:
- sudo su
- gem install bundler
- exit
- git clone [Forked Expertiza repository url]
- cd expertiza
- bash setup.sh
(change config/database.yml, there is no MySQL password by default)
- bundle install
- rails server
After successfully setting up the environment, LogIn to the Expertiza application using necessary credentials.
To navigate to the menu.rb file:
1. Open terminal inside the virtual environment.
2. Navigate to the model folder of the application by typing the following command in the terminal:
cd/expertiza/spec/models
Functionality of Menu model
Menu is a model which gives the functionality to the top menu bar in the Expertiza website. It controls the display of the tabs based pn the user. It links the menu items associated with each tab in the menu using a tree. It directs how these tabs are displayed with regards to different users which have different permission attributes. A super admin has the permission to edit the menu bar, by adding or deleting menu item blocks from it. Upon adding each item, he gets to position it either in the main menu bar or into different subcategories.
Sample Views
The following Menu is displayed for the Student role :
Test entries creation
Mock/dummy objects are needed to be created for any unit testing criteria. These objects are loaded newly and deleted after every testing condition.
Several methods exist for creating such objects, whose parameters need to be designed to satisfy the conditions under test. Using factories command pattern is one such method where few of the attributes are filled in with predefined values when created.
We have used factories and created the mock objects that we need to execute the tests. Menu model require several other mock objects to be created namely Node(this is a subclass in the menu class), menu_item, site_controller, controller_action,etc.
Conditions tested in Menu
A total of 21 testing conditions were required to be performed for testing all the functions in menu model file.
The conditions that needed to be tested are as below:
Node class
1. initialize
In this method, we check whether the parent attribute of the node instance passed is set to nil. We have therefore written a test in which the expectation of the test is that the parent attribute of the node instance is Nil.
2. setup
2.1 In this scenario, the controller_action attribute of the menu item is nil. In this case, the expectation is that the content page path of the current menu item is assigned to the URL variable.
2.2 In this scenario, the controller_action attribute of the menu item is not nil. In this case, the expectation is that the URL of controller_action is assigned to the URL variable.
2.3 In this scenario, the controller_action attribute of the menu item is unavailable. In this case, the expectation is that a customised path is assigned to the URL variable.
3. site_controller
3.1 In this scenario, the site_controller variable is nil. In this case, the expectation is that the site_controller is found by the id and returned. 3.2 In this scenario, the site_controller variable is not nil. In this case, the expectation is that the site_controller variable is returned.
4. controller_action
4.1 In this scenario, the controller_action variable is nil. In this case, the expectation is that the controller_action is found by the id and returned.
4.2 In this scenario, the controller_action variable is not nil. In this case, the expectation is that the controller_action variable is returned.
5. content_page
In this scenario, the content_page variable is nil. In this case, the expectation is that the content_page variable is found by id and returned.
6. add_child
In this scenario, a node is added to the @children list. The expectation is that the current node is added to the @children list and the total number of children are returned.
Menu class
- initialize
1.1 In this scenario, the menu items are nil or empty. The expectation is that the later initialization is terminated and nil is returned.
1.2 In this scenario, the menu items are not nil or empty and the parent id of the node is nil. The expectation is that a hash of menu items is built by name and id and the current node is made a child node of the root node.
1.3 In this scenario, the menu items are not nil or empty and the parent id of the node is not nil. The expectation is that a hash of menu items is built by name and id and the current node is made a child node of its parent node.
2. select
2.1 In this scenario, the by_name hash does not contain the given node name. The expectation is that nil is returned.
2.2 In this scenario, the by_name hash contains the given node name. The expectation is that the menu item for the given name is selected.
3. get_item
In this scenario, the menu item id is passed as a parameter to the method. The expectation is that the menu item is returned by id.
4. get_menu
In this scenario, the menu level is passed as a parameter to the method. The expectation is that an array of all the child nodes at that given level is returned.
5. selected
In this scenario, the expectation is that the name of the currently selected element is returned.
6. selected?
6.1 In this scenario, @selected hash contains menu_id. The expectation is that true is returned.
6.2 In this scenario, @selected hash does not contain menu_id. The expectation is that false is returned.
7. crumbs
In this scenario, the expectation is that a list of menu items is returned based on the contents in the crumbs array.
Test Results and Coverage
A screenshot of the tests passing is shown here:
Coverage Results
Conclusion and Learning Outcomes
After writing the test cases we used SimpleCov to measure the C0 coverage of our rails application. SimpleCov was already installed earlier. After running rake spec to run the test cases, SimpleCov creates a directory called coverage in our rails application folder. This folder called coverage contains an index.html file which when opened in a browser renders an HTML page which gives the C0 coverage of each of the files in the Controllers, Models, Helpers in the app directory.
These are the learning outcomes after performing this project:
- Writing tests using the Test Driven Development approach.
- Writing unit tests for models and controllers in RSpec.
- Understanding the functionality of an already developed application. In our case, before writing the test cases for the menu.rb we had the understand how different models interacted with each other and how each action by different users would make changes in the database schema.
- An understanding of how different tables are structures in the schema in large applications.