DEV Community

Dharam Ghevariya
Dharam Ghevariya

Posted on

My Experience Creating CI Workflows and Contributing Tests to an Existing Project

This week, I focused on setting up a complete GitHub Actions CI workflow and writing tests for a codebase I did not originally create. Both tasks helped me understand code quality, consistency, and the importance of automated testing in a project.

To begin with, I created a ci.yml file that runs on push and pull request to the main branch. The workflow has two major jobs. The first is the test job, which runs on a matrix of Ubuntu, Windows, and macOS to ensure cross-platform reliability. It checks out the repository, sets up Python 3.12 with pip caching, installs all necessary dependencies, runs linting and formatting checks using ruff, performs type checking with mypy(static type checker for Python), and finally executes the full test suite with coverage reporting. The second job is a build job that runs only if the tests pass successfully. It installs the build tools, creates distribution packages using python -m build, and uploads the generated artifacts so they can be reviewed.

To test these workflow, I had created a new PR for more test implementation to my project similarly how I discussed in my previous blog. When created the PR it ran the jobs defined the workflow and ran successfully - you can see by visiting GitHub-Action. Along with that I ran once again before merging this PR to main branch: GitHub-Action. To test the failure, I added a bug in test making the job fail - GitHub-Action, and when committing this changes to main branch it shows a red cross(❌) beside the commit message denoting the failure.

One challenge I ran into involved dependency installation. The project uses PEP 735 dependency groups rather than the older optional-dependencies format. Because of this, the usual pip install -e ".[dev]" command did not work as expected. I had to explicitly install individual development dependencies such as ruff, mypy, pytest, and pytest-cov. This gave me a much better understanding of how dependency standards are evolving and how CI workflows need to adapt.

Writing tests for someone else’s project turned out to be a very insightful experience. Since I was not familiar with the codebase, I started by studying the existing tests. The maintainers followed a simple, consistent style where tests were small, function-based, and relied on minimal setup. They used the built-in tmp_path fixture for file handling and avoided heavy mocking. This made it easier for me to understand their approach and write tests that fit naturally into the project. I focused on two isolated utility functions, log_verbose and human_readable_age, which were good candidates for unit testing. Understanding how verbose logging and time formatting worked required some investigation, and GitHub Copilot was helpful in guiding me through the patterns and suggesting test structures that aligned with the existing style. This is the PR I had raised for it: Test/cli functions

Working through this process also changed how I think about continuous integration. With CI running tests, linting, formatting checks, and type checking automatically on different operating systems, I felt much more confident that my code worked properly everywhere. I no longer had to remember to run all the commands myself because the CI pipeline handled everything for me. It acted like a safety net that quickly showed me if something was wrong. Overall, CI made the whole testing process easier, more reliable, and helped me trust the changes I was making.

Top comments (0)