Setup a Flutter CI/CD with GitLab CI — Part 3

Unit testing Flutter apps in CI Pipeline

Roger Tan
Kin + Carta Created
5 min readOct 8, 2019

--

In the previous post, we learnt how to install Android SDK, Xcode and Cocoapods.

In this post, we will learn how to set up our CI Pipeline.

The most common CI Pipeline in the Mobile world is Build -> Test -> Deploy. But when using Flutter, we run a Unit Test and Widget Tests without building the entire app.
What I’ve learnt, is that it’s probably more efficient to start with unit tests, followed by widget tests as we receive a faster feedback, and if there is a failure, there is no need to build the app.

Creating a unit test lane

Before a job is created, a new GitLab Configuration file .gitlab-ci.yml needs to be generated from the root source of your codebase.

Copy and paste the configuration shown below into your .gitlab-ci.yml.

stages:
- test # All jobs related for testing such as Unit Test

flutter_test: # Name of the lane
stage: test # type of stage
script:
- flutter test # Run Flutter test
tags:
- flutter # Tags for runner
  • stages is used to define stages that can be used by jobs and is defined globally. The value we use will be “test”.
  • flutter_test is our job name.
  • stage is defined per-job and relies on stages which is defined globally. It enables you to group jobs into different stages, and jobs of the same stage are executed in parallel.
  • script This is where the shell script is executed for this job. Here, we will use flutter test to run the unit test.
  • tags is used to select specific Runners from the list of all Runners that are allowed to run this project. We will use flutter which was defined during the runner setup.

When you commit and push to your git repository, you should see the first successfully running job 🎉.

Creating an Android build lane

In this step, we will build our first Android APK.

Firstly, add another value under the stages heading called build as shown in the example below.

stages:
- test # All jobs related for testing such as Unit Test
- build # All jobs related for building app for iOS and Android

Beneath theflutter_test lane, paste the following example (in bold)

####
#### flutter_test lane
####
flutter_build_android: #Job name
stage: build # kind of job
before_script:
- flutter packages get
- flutter clean
script:
- flutter build apk
artifacts:
paths:
- build/app/outputs/apk/release/app-release.apk
tags:
- flutter
  • flutter_build_android is the new job name for building an Android app.
  • stagehas the build value so in the future, we can execute the same stage in parallel when building apps.
  • before_script is the list of command lines which is executed before the job. For these commands, we use flutter packages get to download dependencies and flutter clean to clear the cache.
  • script is a parameter executed by the runner. The valueflutter build apkis used to create an unsigned APK which can be installed on any Android devices.
  • artifacts:paths is a parameter used to define the path where an APK should be saved.
  • tags is used to select specific Runners from the list of all Runners that are allowed to run this project.

Now, let’s commit and push the updated .gitlab-ci.yml file to our repository. We should now have our APK build from the CI Machine. 🎉

Creating an iOS build lane

In this step, we focus on creating an IPA build for iOS devices.

Installing iOS certificate on your machine

Before moving onto the next step, ensure the distribution certificate is installed on your machine. If not, refer to this documentation.

Creating an ExportOptions.plist

Before building and exporting an IPA. xcodebuild needs to know how it should be exported as an archive. For this example, we will use our provisioning profile and export using the method ad-hoc so it can be distributed to our internal end-users.

If you have an enterprise membership, I recommend using the enterprise method so your allocated devices (Limited to 100 per membership annual period) won’t be wasted except if you need to have debugged from the device.

We need to create a new file called ExportOptions.plist and paste the following text (see below) into the file.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>provisioningProfiles</key>
<dict>
<key>BUNDLE_IDENTIFIER</key>
<string>PROVISIONING_PROFILE_NAME</string>
</dict>
<key>method</key>
<string>ad-hoc</string> #adhoc or enterprise
<key>teamID</key>
<string>TEAM_ID</string> #TEAM ID that can find
</dict>
</plist>
  • <key>BUNDLE_IDENTIFIER</key> is the bundle identifier of your iOS app. This is similar to the package name for an Android app. Don’t forget to replace BUNDLE_IDENTIFIER with your previously chosen bundle identifier.
  • <string>PROVISIONING_PROFILE_NAME</string>is the provisioning profile name for signing your iOS app. Don’t forget to replace PROVISIONING_PROFILE_NAME with your previously chosen provisioning profile name
  • The value of <key>method</key> is the way the app is being distributed. It could be development, ad-hoc, enterprise or appstore .
  • <key>teamID</key> is the ID which Apple assigns to your membership Apple Developer Program which can be found on this page. Don’t forget to replace TEAM_ID with the value from the membership details page.

Configuring an iOS build lane

In this section, we will build an iOS flutter project from the CI.

Beneath the flutter_build_android lane, paste the following example (in bold).

####
#### Unit test and flutter build android
####
flutter_build_ios:
stage: build
before_script:
- flutter packages get
- flutter clean
script:
- flutter build ios
- cd ios
- xcodebuild clean archive -workspace Runner.xcworkspace -scheme Runner -archivePath RunnerArchive
- xcodebuild -exportArchive -archivePath RunnerArchive.xcarchive -exportOptionsPlist ExportOptions.plist -exportPath ./build
artifacts:
paths:
- ios/build/Runner.ipa
tags:
- flutter
  • before_script is the list of command lines which is executed before the job. For these commands, we use flutter packages get to download dependencies and flutter clean to clear the cache.
  • script is a parameter executed by the runner. For the list of command lines:
    - flutter build iosis used to build an iOS project.
    - cd ios we will change the directory to the ios folder.
    - xcodebuild clean archive [..] this is where an iOS project can be archived.
    - xcodebuild -exportArchive [..] these are a process of code signing your archive and generating an IPA.
  • artifacts:paths is a parameter used to define the path where an IPA should be saved.
  • tags is used to select specific Runners from the list of all Runners that are allowed to run this project.

After you commit and push the updatedgitlab.yml, you should now see your first iOS app build. 🎉

On the next post, we will learn how to deploy our APK and IPA via a distribution platform such as Visual Studio App Center or an equivalent.

--

--