20

The standard practice in the Objective C world has been to follow that laid down in the Java world when it comes to code management. i.e. Your application source code goes in one directory, and your unit test code goes in another.

I've always found this a bit of a pain. Especially as I tend to organise XCode the same way. The issues that annoy me are:

  • Having to keep all the various groups in sync in terms of naming, etc.
  • Not easily being able to see which classes have matching test classes.
  • Having to scroll up and down through hierarchies all the time as I'm bouncing between tests and source.

So I've been thinking - What if I put the test code beside the source code? In the same directory. And in XCode I can then have the test code sitting with the source and easily locate and see the matching classes.

Has anyone tried this? Is it workable? Or is there another solution?

1
  • 6
    One purpose to keeping the tests in a separate set of folders is to make packaging the deployed product more straightforward. Java builders that I'm familiar with (Ant, Maven) will package up entire folders. In your method, you will have to explicitly enumerate all and only the objects you want to be finally deployed Commented Jul 24, 2015 at 14:13

3 Answers 3

5

As Uncle Bob always says, your tests should not be coupled to the structure of your application (great blog discussing this topic).

Doing what you're suggesting sounds like you may run into issues with deployment, or other aspects of development... But the biggest issue I see is you'll be tempted to (if not forced to) couple your test-suite tot your application structure.

I wouldn't recommend allowing yourself to deal with the world of future headaches (from something simple such as a small package refactor) that come with this decision.

1
  • 9
    When uncle bob said that tests should not be coupled to the structure of your application, he wasn't talking about tests in the same folder or a separate folder, he was talking about code design in general. So I think the evidence you provided is not related to this question.
    – Basil A
    Commented Oct 30, 2020 at 21:30
4

I tried this and won't recommend it... if you have only a few of classes per package could seem nice but, let's imagine a package with 20 production classes.. it will have 20 tests files placed there also? For me will be too much...

Furthermore, maybe with that structure that is not following the standard convention you should need to configure manually some of the features of your build tool/CI pipeline with an specific setup and this, in my opinion, doesn't foster interoperability

Regarding the pains you mention I think with a modern IDE they can be solved:

  • Having to keep all the various groups in sync in terms of naming, etc

This can be solved by using the functionalities included to generate the tests automatically. If then you are changing the name of the class, you can change it by the IDE that will change the name itself and all its references, including the test related name.

  • Not easily being able to see which classes have matching test classes.

Again modern IDE has a functionality to easily check which test sources are pointing to your production class, even if there are many tests spread through different files

  • Having to scroll up and down through hierarchies all the time as I'm bouncing between tests and source.

Same here, if you right click in any class you will have an option to go to the tests and a button to go back is also provided.

All of these nice features that the IDE provides will be subject to manual configuration if you take the approach mentioned in your question.

0

For Java land, I prefer to organize in the approach prescribed by Maven and Gradle's defaults. However, I don't have a separate .test sub-package instead I keep to the same package when I am unit testing the component (that way I don't have to make methods public if I don't need to and rely on default visibility. Secondly in Java land the tools are preconfigured to handle that scenario by default.

Following up to the above... regardless of what language, I package by functional group by default and by types for common utilities. This is different than what most JavaScript and other code generators do, which lump everything by type and is propagated by insert negative adjective of choice developers.

Granted that I do that for TypeScript/Javascript, Python land where the source is the executable, I would keep unit tests with the file they are testing with with the .test.ts suffix. This keeps the tests close to the code and you'd know the test is for the code because their base names are exactly the same.

Composite tests where you test multiple components are also kept in the same spot as the code since one of the root module where the test starts from would be in the same folder anyway. There's no need to make one test file per module if the module files are very coupled.

BDD/TDD tests, I would keep it in a __test__ sub-folder since that's Jest's default. These tests try out multiple components and are related to a business transaction rather than a simple sanity of testing different inputs to handle component edge cases.

You can tell a BDD/TDD test vs a unit/composite test in that your describe() is generally a business scenario rather than the module name.

The good and bad part about JavaScript is its very much a free for all. Every framework does things their own way. I stuck with what by react-native-builder-bob uses since I write react native libraries.

<root>
|- src/ (sources)
   |- /__test__/ (tests only)
|- lib/commonjs/... (generated output)
    |-/module/... (generated output)
    |-/typescript/... (generated output)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.