Aug 2022 - Dec 2022
Skills: ReactJS • Python • Flask • Agile • Scrum • MySQL
Coursework Project
8 min read
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).
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
Other deliverables and requirements of the project include
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
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.
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.
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:
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:
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.
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.
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 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.
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 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.
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.
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.