XCUITest — Test Automation Organization

Over the past several years we have made adjustments to our test case file structure and files to improve maintainability and readability. There are several ways you can organize your test files but I wanted to discuss our current approach and how it has helped us. Hopefully you can find these ideas beneficial to your project as well.

Folder Structure

We break our test files apart into the following folders shown above: Elements, Functions, Stubs, Tests.

  • Tests: this is where the actual test files are stored. If a Business Analyst, Product Owner, or another team member wants to review the test cases and expected results, this is where they go. We additionally break down this folder further by making subfolders for the different areas of the application making it easier to find the exact test files you are looking for.
  • Functions: this is where are page/screen objects are stored and also broken down into subfolders for the different areas of the application. These files contain the functions that interact with the screen/objects, perform verifications, wait for elements, or contain element functions (more on this later). Modularizing this code into separate test files really help to improve the maintainability and readability of the test files. BA’s or other team members (outside of QA) typically won’t care how we go about performing the verification of the scenarios, but they want to be able to easily read the test files to confirm the scenario performed and expected results.
  • Stubs: Depending on if you are using stub data for your automation and what kind of framework you are using, you may or may not need this. We currently use https://github.com/Subito-it/SBTUITestTunnel for our stubbing solution, so our stub files are managed within this folder. This article will not cover this stubbing framework; however, if you are interested you can check out this article instead https://rlukasik.medium.com/xcuitest-stubbing-network-calls-c04cf69ddb7f
  • Elements: a.k.a Locators. These files contain the locators to locate the elements/objects on the screen that your automation tests will interact with.


Here is an example test file:

  • Each test case must start with “test”
  • The setup function runs before every test. In order to avoid launching the test for every test case, we use the workaround by setting a boolean. We do this due to the time of our application launch + login time. Even with using stub data, this would add several seconds onto each different test case. To reduce the overall test run time, we run all test scenarios for a particular screen and use tearDown blocks (when needed) to reset each test back to where the setUp ends.
  • login is the screen/page object — an instance of the “function” file which will be shown in more detail next.
  • Returning “self” from functions allows you to chain function calls. You will also see this in the function file example.


Here is an example functions file setup:

  • These function files contain the functions that are called by the tests to interact with the application.
  • These functions use the element locators maintained in the Element files (shown next).
  • “Helper” function files may also be created that contain functions for functionality common to multiple screens, such as waiting on elements or interacting with alert dialogs. Shown here is a call to WaitHelper which is a Helper File.


The locators can be organized using swift enumerations.

  • Using Identifiers, which is a recommended practice anyways, works well for this setup.
  • This approach is unable to take parameters so this didn’t always work for all locators for us. For these instances, we create Element Functions section within the Functions files as needed. Example:



Test Engineer Expert, Dog Mom

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store