There are few reasons why tests are in different namespaces.
Drupal have several different types of tests
- WebTestBase (WTB), aka simpletests or integration tests
- BrowsertestBase (BTB), integration tests (all WTB will eventually be replaced by equivalent BTB)
- KernelTestBase (KTB), a barely bootstrapped version of Drupal, not an integration test but a lot more than a true unit test
- JavascriptTestBase (JSTB), an integration test that is Javascript aware
- UnitTestCase and PHPUnit_Framework_TestCase, unit tests
Note that integration are also called functional tests. I am going to ignore the difference between UnitTestCase and PHPUnit_Framework_TestCase right now and lump them together as unit tests.
The five different test types are all in different namespaces so the test discovery process can find them and place them into five groups. The test runner allows the various test groups to be run together, and also invoke them properly during runs.
For example, if making a big change, you can run all unit tests locally as a sanity check (running all of the take about a minute on a normalish local machine).
Tests associated with a particular module are also in the modules namespace, so you can easily run all tests for that module, and they won't be discovered if that module is disabled. For example, integration tests take along time (usually between 30 seconds and 4 minutes each). You can just run all of the Field UI tests at ones if you are doing work there.
The test runner also allows you to run all of the tests in a particular directory. This allows you to target a particular core subsystem that isn't in a module. For example, you can run all of the database kernel tests at once this way.
Some subsystems also define their own test bases. For example, the migration system defines its own test bases to centralize common functionality and to to have a common setup.
Tests also make frequent use of traits to share code between different types of tests.
The particular case you mention is an oddity. In a perfect world, the t()
function wouldn't be used in object oriented code; the injected translation service would be used which could then be mocked in unit tests instead of needing to use shenanigans like shadowed globals.