You are correct. Professionals do have different versions of their code for different purposes. Different programming languages handle this in different ways, let's take JavaScript as an example:
To design an interactive website you write a program in JavaScript. JS is an interpreted language so it doesn't need to be compiled (in to a machine readable but not easily human readable format). This source code can be sent from the server to a user's browser and run directly as it is. This is easy to debug but is not the most efficient way to transfer large codebases across the internet.
There are several ways of tackling this, but one is Webpack. It can take your program, place all the code in one file, remove all the comments, spaces, and line breaks, and rename all of your variables to be short names e.g. a, b, c. This single file, traditionally called bundle.js, can then be sent to the user's browser, which won't take so long as it will be smaller.
The problem is when trying to debug this bundle in your browser nothing looks the same as in your source code, it's possible, but hard to read. Webpack has a trick for this too, it can make something called a source map available on another url such that your browser, if it knows where to look, can reconstruct the original source code to make it easier to debug again.
Other languages have similar ideas but implemented in different ways. For example C++, which is a compiled language - so your source code is turned into something the machine can run directly, has many optimisations it can add between your source code and what the target computer runs; removing debugging information, adding common optimisations of you statements, etc.
All of these are jobs for a computer to do, they are complex repetitive tasks so we let the build pipeline do it for us.
It can be necessary to maintain two, or more, different copies of the source code of a program that will diverge over time. If you are still being paid for support on version 3, but you are working on version 4, you need to be able to add new features to v4 that would break v3, but still need to add bug fixes to v3. This is where source control and branches can help out.
You mention testing. We often do have different parts of the system designed to only ever be run when we are testing; test infrastructure, stubs, mocks, etc. But these are in addition to the main program's source code and are not considered a separate copy. The tests should, in general, be running the main source code to test it works and not an approximation. This isn't always possible and sometimes we use fake implementations such as in-memory databases so that our tests run faster, but only when we are testing other parts of the system and the database can be considered not under test in this case as it is tested elsewhere.