The API is 100% intended for internal use only, but someone insists on ignoring that and consuming the private API anyways. Instead of forcing them to write their own headers which silently break at runtime when function signatures change in certain calling conventions which don't check those signatures, I instead allow them to include headers with a few keywords like "private", "internal", "do_not_use", or "i_am_voiding_my_semver_warranty" in the path, perhaps only after they make some similarly scary #define s, so it's at least a build failure.
I see this a lot in Java libraries, for instance.
Generally, proper unit testing is at odds with strict scope restrictions in the tested code. I guess we need more allowances fornunitbtesting at the language level to fix that. E.g. allow testing code to be marked as such and ignore that certain things are declared private, but in turn only allow it to be run in a testing context, but not regular builds, to prevent abuse.
This is a limitation imposed by the IDE, not the language. There's nothing stopping you from compiling code and tests into the same dll that you unit test. Likewise there is no need to separate code from the tests (apart from different files), they can simply not be included in release builds.
Source layout structure does not have to be a 1 to 1 mapping of the output structure.
That is what [assembly: InternalsVisibleTo()] is for.
Unit tests should only exercise public interfaces, with internals and private parts being tested as side effect of calling them.
Another situation is checking numerical code for correctness and accuracy. There it is extremely advantageous to have testable small functions that map to individual mathematical expressions. But these are again implementation details that need to be hidden behind interfaces.
Your numerical code example can be achieved with an Assembly of internal functions/methods, exposed only to the implementation and unit tests.
Of course, this is easy to do in a greenfield project from the start, not so easy on legacy code.
I have to clarify that I'm not fixated on C#. Sure, you could create a helper assembly in .NET that is a mess of essentially of disembodied functions for computing every slightly more complex function that happens to be in your program. But this breaks OOD.
In C/C++ you can't do quite the same. The best you could do there is break OOD and try to hide these global functions by using private headers (which are ugly in their own ways).
So I usually make most stuff public as such, but put internals in a namespace/scope that makes it clear that these are implementation details. Relying on implementation details always carries the risk of breaking when upgrading.
This allows for a lot of flexibility when needed, while also not polluting the "truly public" API.