How to use Git Hooks in Flutter to run your tests automatically
Automating software development processes can greatly improve efficiency and maintain code quality. Git hooks offer an effective way to automate various tasks within your development workflow. In this post, we will explore how to use Git hooks to automatically run tests in your Flutter project, ensuring that your codebase remains robust.
Installing requirements
Before we begin, ensure that you have Git installed. If not, you can easily set it up using this guide. Additionally, make sure you have Flutter installed on your machine. If Flutter is not already installed, you can do so using the instructions provided here.
Creating new project
Let us start by creating a fresh project. Open your preferred command-line interface (CLI). I will be using the command prompt on Windows. To access it, simply press the Windows button, type "cmd", and click on "Command Prompt".
In the CLI, navigate to the directory where you want to create your project. We can create a new project by executing the cd
command followed by the desired path, and then hitting "Enter". In my case, the command is: cd Documents\Codeonwards\demo
.

Now we can execute the following command to create a new project flutter create flutter_git_hooks
.

Creating a new Git project
Go to your GitHub, GitLab, Bitbucket, or other Git distributed control system and create a new project. I will be using GitHub.

Once you created a new Git project we need to execute the following commands to add our Flutter project to the Git project.

1. cd flutter_git_hooks
: to navigate inside our project.
2. git init
: to initialize Git.
3. git add .
: to add all the files of our project.

4. git commit -m "first commit"
: To capture a snapshot of the currently staged changes.

5. git branch -M main
: To rename the default branch to main
.
6. git remote add origin https://github.com/TijnvandenEijnde/flutter_git_hooks.git
: To add a remote repository to our local project. Make sure that you use your own project here.
7. git push -u origin main
: To upload the changes to the Git repository.

Now you will see that our project is pushed to a Git distributed control system, in my case, GitHub.

Git hooks
Now with everything set up, we can start creating our Git hooks.
Creating the directory structure
Inside our project, we need to execute the following command: git config core.hooksPath .githooks/
. This command is used to configure Git to look for the hooks in the given directory .githooks/
.

Now it is time to open the new project inside your favorite IDE. I am using IntelliJ but this is not required any IDE should do fine. Once the project is opened we need to add the .githooks
directory in the root directory.
Inside this directory, we need to add two files with the following names pre-commit
and pre-push
. These files should not have a file extension.
If you followed the instructions correctly your folder structure should look as follows:
|-- flutter_git_hooks/
|-- .githooks/
|-- pre-commit
|-- pre-push
To give you a more clear picture, here is a screenshot of the directory structure inside my IDE.

With the directory structure complete we can move on to writing the code for the files.
pre-commit
The pre-commit
bash script we will create runs the Dart code formatter. The purpose of the script is to ensure that our codebase follows the Dart formatting rules. The pre-commit
script will run every time you execute git commit
. That is why we are not running any tests in this script, because running tests on every commit can become quite annoying, but know that it is possible. See the pre-commit
script below:
#!/usr/bin/env bash
#dart format
printf "\e[33;1m%s\e[0m\n" 'Running dart format'
result=$(dart format .)
result_lines=$(echo "$result" | wc -l)
if [ "$result_lines" -gt 1 ]; then
echo "$result"
printf "\e[31;1m%s\e[0m\n" 'Dart format applied changes, please recommit'
exit 1
fi
echo "$result"
printf "\e[32;1m%s\e[0m\n" 'Finished running dart format'
To make sure you understand the script we will break down the script step by step:
1. Shebang Line
#!/usr/bin/env bash
This line specifies the interpreter for the script, indicating that it should be executed using the Bash shell.
2. Comment
#dart format
This is a comment that indicates the purpose of the upcoming command: running the Dart code formatter.
3. Printf Command
printf "\e[33;1m%s\e[0m\n" 'Running dart format'
This line uses the printf
command to print a colored message to the terminal. The color code \e[33;1m
sets the text color to yellow, and \e[0m
resets the text color. The message "Running dart format" is displayed in yellow.
4. Running dart format Command
result=$(dart format .)
This line runs the dart format
command on the current directory (.
), which attempts to format all Dart source files found in the directory. The output of the command (which includes any error messages) is captured and stored in the variable result
.
5. Counting Result Lines
result_lines=$(echo "$result" | wc -l)
This line pipes the content of the result
variable into the wc -l
command, which counts the number of lines in the output. The resulting count is stored in the variable result_lines
.
6. Checking for changes
if [ "$result_lines" -gt 1 ]; then
echo "$result"
printf "\e[31;1m%s\e[0m\n" 'Dart format applied changes, please recommit'
exit 1
fi
This if
block checks if the output of the dart format
command covers multiple lines. If it does, it implies that file changes were made. The script then shows the formatted output, a red message indicating the need to recommit changes, and exits with code 1
. Which typically indicates an error or non-successful execution.
7. Displaying a success message
echo "$result"
printf "\e[32;1m%s\e[0m\n" 'Finished running dart format'
If no changes were detected and the script has reached this point, the formatted output is displayed, and a success message is shown in green, indicating that the Dart formatting process has been completed successfully.
pre-push
The pre-push
bash script will run Flutter's lint formatter and tests using the flutter analyze
and flutter test
commands. The script will run every time you execute git push
. See the script below:
#!/usr/bin/env bash
#flutter analyze
printf "\e[33;1m%s\e[0m\n" 'Running flutter analyze'
result=$(flutter analyze)
if [ $? -ne 0 ]; then
echo -e "$result \n"
printf "\e[31;1m%s\e[0m\n" 'Flutter analyze found the above issues, please fix them before pushing'
exit 1
fi
echo "$result"
printf "\e[32;1m%s\e[0m\n" 'Finished running Flutter analyze with 0 issues'
# flutter test
printf "\e[33;1m%s\e[0m\n" 'Running flutter test'
result=$(flutter test)
if [ $? -ne 0 ]; then
echo -e "$result \n"
printf "\e[31;1m%s\e[0m\n" '1 or more test(s) failed'
exit 1
fi
echo "$result"
printf "\e[32;1m%s\e[0m\n" 'Finished running flutter test'
Let us break down the script step by step:
1. Shebang Line
#!/usr/bin/env bash
This line specifies the interpreter for the script, indicating that it should be executed using the Bash shell.
2. Comment
#flutter analyze
This comment indicates that the script is about to execute the flutter analyze
command.
3. Printf Command
printf "\e[33;1m%s\e[0m\n" 'Running flutter analyze'
This line uses the printf
command to print a colored message to the terminal. The color code \e[33;1m
sets the text color to yellow, and \e[0m
resets the text color. The message "Running flutter analyze" is displayed in yellow.
4. Running flutter analyze Command
result=$(flutter analyze)
This line runs the flutter analyze
command, which checks if the code is following Flutter's linting rules. The output of the command (which includes any error or warning messages) is captured and stored in the variable result
.
5. Checking for linting issues
if [ $? -ne 0 ]; then
echo -e "$result \n"
printf "\e[31;1m%s\e[0m\n" 'Flutter analyze found the above issues, please fix them before pushing'
exit 1
fi
This block checks the exit status of the flutter analyze
command. If the exit status is not equal to 0
(indicating any errors or issues were found during execution), the script proceeds to display the analysis output, a message in red indicating issues were found, and exits with an exit code of 1
.
6. Displaying a success message
echo "$result"
printf "\e[32;1m%s\e[0m\n" 'Finished running Flutter analyze with 0 issues'
If no issues were found during static analysis and the script has reached this point, the analysis output is displayed, and a success message is shown in green, indicating that the analysis was completed successfully with no issues.
7. Comment
# flutter test
This comment indicates that the script is about to run the flutter test
command for running tests in the Flutter project.
8. Printf Command
printf "\e[33;1m%s\e[0m\n" 'Running flutter test'
Similar to the previous cases, this line uses printf
to print a yellow-colored message indicating that the script is running the tests.
9. Running Flutter Test Command
result=$(flutter test)
This line runs the flutter test
command to execute tests for the Flutter project. The output of the command (which includes test results and any error messages) is captured and stored in the variable result
.
10. Checking for failing tests
if [ $? -ne 0 ]; then
echo -e "$result \n"
printf "\e[31;1m%s\e[0m\n" '1 or more test(s) failed'
exit 1
fi
This block checks the exit status of the previous test command. If the exit status is not equal to 0
(indicating test failures), the script proceeds to display the test results, a message in red indicating test failures, and exits with an exit code of 1
.
11. Displaying a success message
echo "$result"
printf "\e[32;1m%s\e[0m\n" 'Finished running flutter test'
If all tests have passed and the script has reached this point, the test results are displayed, and a success message in green is shown, indicating that the tests were executed successfully.
Running the scripts
We have created the pre-commit
and pre-push
files. As mentioned earlier, the pre-commit
file runs automatically when we use git commit
, and the pre-push
file runs automatically when we use git push
.
Git commit with formatting errors
When we run git commit
while we have formatting errors, the script will show the following:

The script executes the dart format .
command. Whenever it applies changes, the script notifies us to recommit the changes.
Git commit without format errors
When we run git commit
without formatting errors, the script will show the following:

If during the script the flutter format .
command did not apply any changes. The staged files will successfully be committed.
Git push with failing tests
When we run git push
while we have failing test cases, the script will show the following:

The script executes two commands: flutter analyze
and flutter test
. If any of these commands encounter issues/errors we will be notified and have to make the adjustments ourselves.
Git push without failing tests
When we run git push
and all our tests succeed, the script will show the following:

If both the flutters analyze
and flutter test
command do not find any issues/errors our stages changes will successfully be pushed to our remote repository.
Conclusion
Using Git hooks in your Flutter workflow can significantly boost efficiency and code quality. Automating tasks like formatting, analysis, and testing contributes to consistent and error-free code. In this post, we went over the essential steps to set up Git hooks, helping you to maintain a streamlined and reliable development process.