Set up your GitHub Actions CI Workflow
- Create a
.github/workflows
folders in the root of repo - Create a workflow YAML file,
ci.yml
, for the CI job as below
name: ci
on:
pull_request:
branches:
- main
push:
branches:
- main
jobs:
lint:
name: ESLint
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install node dependencies
run: npm ci
- name: Run ESLint
run: npm run lint
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: '20'
cache: 'npm'
- name: Install node dependencies and run Tests
run: npm install-ci-test
NOTE: This workflow runs linters followed by automated unit tests. It will be triggered whenever a pull request is made or someone pushes commits to the main branch.
How did your partner's repo and testing setup differ from yours?
First of all, my partner uses pytest for Python, so the testing setup was completely different from mine. One thing I noticed was the absence of a config file for the tests. I had to update my .eslintrc.cjs
to inform ESLint that my repo uses Jest. Additionally, there was no setup to add npm scripts to package.json
to run the tests, as long as pytest is installed. Without adding anything, a simple pytest does the same trick as npm run test
. I find the testing setup for Python much simpler and easier than for TypeScript.
What was it like writing tests for a project you didn't create?
While writing unit tests, there were certain points where I needed to revisit the target code that I wanted to test and make changes to the original code. However, I was unsure if I was allowed to do so, considering the original code was not written by me. For instance, exit()
was used when a FileNotFoundError
occurred in the original code.
try:
with open(input_file, "r") as file:
text_lines = file.readlines()
except FileNotFoundError:
print(f"Error: {input_file} not found.")
exit()
The issue was that the program did not exit immediately when I attempted to test this code. After some research, I discovered that using raise
instead would achieve the desired immediate program exit. This way, I can test the code to ensure that the program raises an exception, as shown below.
@patch("builtins.print")
def test_process_non_exist_text_file(self, mock_print):
with self.assertRaises(FileNotFoundError):
process_text_file(
"examples/test-folder/invalid.txt", "examples/test-folder-output"
)
mock_print.assert_called_once_with(
"Error: examples/test-folder/invalid.txt not found."
)
More details in GitHub: pr
What do you think of CI now that you've set it up for yourself?
There were many times when I pushed commits to the main branch before checking for linter errors, which may break the program. I realized that setting up the CI workflow makes a developer's life so much easier, as it reduces the number of things to worry about by preventing minor linter bugs and saving a significant amount of time.
More details in GitHub: pr
Top comments (0)