Learning Journey Planning System

Agile and Scrum methodologies in practice

Aug 2022 - Dec 2022

Source Code

Skills: ReactJS • Python • Flask • Agile • Scrum • MySQL

Coursework Project

8 min read


Introduction

This project was done in a group of 6, as part of the coursework for IS212 - Software Project Management module in SMU.

The overall goal of the project is to allow students to gain hands-on experience running and applying Agile and Scrum methodologies to a software project in a collaborative environment, as well as working with an external customer.

As such, frontend design is not a priority, but rather the focus was on the collaborative software development experience, adopting modern software development practices during the process such as Agile, Scrum, test-driven development (TDD), and Continuous Integration & Continuous Delivery (CI/CD).

Requirements

The end product outcome from the project should be a (working) prototype of a learning journey planning system (LJPS) which would minimally support five core features, namely

  • Users should be able to select a role they want and see a list of skills required
  • Users should be able to see the courses they can take to acquire those skills, and add/remove - them on their learning journey
  • CRUD functionality for roles
  • CRUD functionality for skills
  • Assigning skills to roles and assigning skills to courses

Other deliverables and requirements of the project include

  • Usage of a version control software (e.g., Git)
  • Rough system design represented using the Context, Container, Component, Code (C4) model.
  • Test cases as evidence of TDD
  • Any CI pipeline script that have been used
  • Documentation of sprint meetings, planning, retrospective, and backlog items
Process
Initial setup and planning

Before diving into coding, we had to do a initial setup and planning for our project. This meant setting up the coding environment, writing our user stories and then estimating them, and then finally holding our first sprint planning meeting.

For our software tools, we decided to go with the following

  • Github : Version control, one that is most familiar by everyone in the team
  • Jira : Issue tracking software, where the main bulk of our documentation will be housed in

Jira also has Github support, allowing the team to easily track the branches, commits, and pull requests created for a Jira ticket at a glance.

After splitting the workload, we finally came up with most of the user stories required to complete in order to achieve the 5 core functionalities of the first software release.

user story example
Example of a user story

The bulk of the stories were estimated using the planning poker estimation technique, while the rest of the stories were left to be assigned a story point at a later date due to uncertainties.

Lastly, before starting on development, we did a rough mock-up of a C4 model so that the team has a can refer to and align against during development. This helped us minimize any wasted time correcting errors and misunderstandings in each member's concept models of the system.

c4 diagram
C4 container diagram
Tech stack

For our tech stack, we chose to use Python and Flask with MySQL for the backend due to familiarity, and ReactJS for the frontend as we wanted to pick up something new (and widely-used within the industry) that was not taught in the school curriculum, and what better way was there to learn a new skill than applying it on a project, right?

Other libraries we used alongside ReactJS include:

  • Notistack : Snackbar alerts to reflect status change on the UI
  • Material UI: React component UI for quick styling
  • Formik : Form and input validation library
create role form
Role creation form
create learning journey form
Learning journey creation stepper form

We also set up a pre-commit linter using husky and flake8, to smoothen our developer experience and standardize code written across the board.

Finally, to practice TDD and increase the reliability of our code, we used the following libraries / frameworks to do so:

  • Jest : Javascript testing framework
  • UnitTest : Python testing framework
Sprint cycles

Prior to the start of every sprint, the team would gather for 30mins to 1hour to conduct a Sprint Planning session, where we discuss and reestimate (if needed) user stories that needs to be completed in the coming-up sprint, before assigning them to members.

As we are all juggling 3-4 other modules during the semester, we decided to conduct a daily-scrum meeting (DSM) every 3-4 days instead of daily, where the team comes together to report on what have been done, what will be done, and if there are any blockers faced during the development process.

To conclude, at the end of each sprint, a Sprint Retrospective is conducted to go over the work done during the sprint (completed or not), so that the team can learn from any mistakes or good practices exhibited by some members. This allows us to be able to conduct subsequent sprints more productively and efficiently.

This becomes more evident as the team is able to see progress towards the end of the term, when the velocity of the team increased significantly.

sprint2 burndown chart
Burndown chart (sprint 2): velocity of 42 points
user story example
Burndown chart (sprint 3): velocity of 57 points
Unit and integration tests

The content for unit tests were gone through pretty late in the semester, therefore we implemented these tests between sprint 2 and sprint 3 of the process. Some code snippets of tests will be shown below.

componentsLib.test.js
const CustomException = (message) => {
  const error = new Error(message)
  error.code = 'CUSTOM_ERROR_CODE'
  return error
}

describe('componentsLibTest', () => {
  describe('getTextColor active', () => {
    test('ACTIVE', () => {
      expect(getTextColor(STATUS.ACTIVE)).toBe('green')
    })
    test('PENDING', () => {
      expect(getTextColor(STATUS.PENDING)).toBe('orange')
    })
    test('RETIRED', () => {
      expect(getTextColor(STATUS.RETIRED)).toBe('red')
    })
  })
  ...
})
Unit test snippet using Jest testing framework

Unit tests using Jest are pretty straightforward, using the describe method in Jest to check if a given input into a method gives the expected output.

unitTest/integration_test.py
class bTestCreateReadUpdateHappy(unittest.TestCase):
  course_url = "http://localhost:5001/courses"
  role_url = "http://localhost:5001/roles"
  skill_url = "http://localhost:5001/skills"
  staff_url = "http://localhost:5001/staffs"

  # Course
  def test_create_new_course(self):
    API = self.course_url + "/TestCourse1"
    data = {
        "course_name": "Test Course 1",
        "course_desc": "This is to test course 1",
        "course_status": "Active",
        "course_type": "Test Type",
        "course_category": " Test Category",
    }
    response = requests.post(API, json=data)
    self.assertEqual(response.json()["code"], 201)
    self.assertEqual(response.json()["data"]["course_id"], "TestCourse1")
  ...
Integration test snippet using UnitTest testing framework

Integration tests are slightly more tricky, and it is required that we mock certain API calls and data and check if the return result from these calls are as expected.

However, mocking API calls and data should not be used too much since there is a chance that the API may change in the future, and if the corresponding mock API in the tests are not updated, it may give the developer the ‘illusion’ that the new code is healthy, when in reality the tests were not updated to match the change in code.

CI / CD

Using Heroku’s ClearDB, we were able to provide an environment that is always updated with the latest build for testing among the developers, as it is connected to the Github repository. This allows developers to work with a ’single source of truth’ (database-wise), so that we can be sure that our changes will be working for the rest as well, instead of just using localhost.

db deployment status
Deployment status of database on Jira
Learnings

There were definitely a lot of learnings to be had, having to design a project from scratch and execute it using the agile software delivery process.

There are definitely many moving parts in a team, and only now that I realize the challenge of co-ordinating many different moving parts in a software-development process.

I‘ve also come to realize the importance of testing, to not only ensure the reliability of code, but also serves as a form of documentation for others, as well as a tool that can be used to build up developer confidence in their own code.

Chew Yi Xin 2023  •  Last updated Feb 2024