But... it works on my machine!

"But... it works on my machine" can be attributed to differences in configuration, library dependencies, or operating systems. It's crucial to test in similar environments and collaborate as a team to ensure consistent performance. Discover potential solutions to address this issue.

But... it works on my machine!


This article was meant to be a collection of phrases that developers often repeat in most projects, expressing in a few words important situations in which any team leader must take action. However, the first one deserves its own post ;)

— But... it works on my machine!

For those of you who are familiar with it, you have two options: either start laughing to relieve the tension or start crying because you know what's coming next. This expression is usually accompanied by connectivity problems when there's a silence waiting for an explanation of why "someone uploaded something" that doesn't work in production, or in the best-case scenario, in the staging or pre-production environment, and unfortunately, it coincided with client testing.

The causes of such issues are many, and here are some ideas to get started:

💡 Note: I'll use the terms "programmer" or "developer" as they characterize the professional based on the type of problem. I'll also make use of Python frameworks.

Configuration Problems: Often, a programmer may have configured their local environment differently from the production environment or another developer's setup, especially when working with a remote team where development environments are not controlled. As a result, a function or feature may work correctly on their machine but not elsewhere.

💡 For such cases, it's ideal to have virtual environment scripts or Ansible playbooks that can configure the environment consistently for all developers.
💡 A virtual environment is a directory containing a specific version of Python and all its associated packages. Virtual environments are perfectly isolated, so you can have as many virtual environments as you want on your Mac or Linux and always know which one you're working with.
💡 Ansible® is an open-source IT automation tool that automates provisioning, configuration management, application deployment, orchestration, and many other manual IT processes. Unlike other simpler management tools, Ansible users (such as system administrators, developers, and DevOps) can use Ansible automation to install software, automate daily tasks, provision infrastructure, improve security and compliance, patch systems, and share automation across the organization.

Missing dependencies or different versions: A programmer might have all the necessary dependencies installed on their machine, but when sharing the code with others, they may find that some dependencies are missing or in different versions, which can affect the software's functionality.

Recommendation: Use Poetry instead of requirements.txt

💡 Tools like PIP, Conda, or simple requirements.txt files can't solve this dependency management problem in large projects. In fact, they contribute to this nightmare in many ways. To end your suffering, the Python open-source community developed Poetry, an amazing dependency management tool with nearly 26,000 stars on GitHub and frequent updates.
💡 Poetry is a dependency and packaging management tool for Python. It allows you to declare the libraries your project depends on and manages them (install/update) for you. Poetry provides a lock file to ensure reproducible installations and can build the project for distribution.

Test Data: If a developer tests with specific data on their machine and doesn't consider other possible scenarios, they can easily get different behavior than expected when testing in a broader environment or with real data.

💡 During the development stage, unit testing is the developer's responsibility, and it should follow the Test-Driven Development (TDD) methodology. Checking the functionality of small functions is straightforward and doesn't require complex data to verify. However, regression, integration, functional, and acceptance testing are already part of QA's normal activity and will require a well-designed data usage methodology.

Different Operating Systems: Each operating system can have peculiarities that affect an application's behavior. What works on a machine with a specific operating system might not work on another with a different OS.

This becomes a problem, for example, when you need to compile apps on different OSes (iOS, Android, etc.).

💡 As we've seen, any variation in the development environment within the team is a problem, so we recommend standardizing criteria. Our recommendation is for everyone to work on Linux, preferably the same version. If this is not possible, the use of all the aforementioned tools will be necessary, but it will triple the effort, involving the dedication of a DevOps expert to correctly configure development environments on each machine, a cost that really doesn't justify the benefits. In the end, maintaining a heterogeneous development environment leads to chaos. There are alternatives to avoid developers having to install an OS on their machine, such as desktop environments in the cloud. They come at a significant cost, but in projects where security is paramount, they should be considered.

Network Environment: In applications that require network access or external services, differences in connectivity and infrastructure can cause issues. An application might work well on a local network but fail on an external network.

💡 Repeating previous situations, adding the complexity of infrastructure, again, any good application should be able to detect these situations, and a good testing methodology is necessary. QA must exist and review all unit tests to assess if the developer should add new ones.

Database Configuration: If the database configuration differs between machines, it can lead to unexpected behavior and errors.

💡 Test database schemas should be identical to production ones, although the data can be modified to prevent privacy issues or information leaks. Ansible and Docker are two essential tools to avoid configuration problems in systems.

In summary, to avoid surprises, it's essential for developers to test their applications in environments similar to production and use tools to manage dependencies and configurations in a simple and consistent manner. Additionally, though not explicitly mentioned, collaboration and teamwork are fundamental to ensuring that applications work coherently on different machines and environments.