You want to create a test for a new or existing Meshery command? Good. This tutorial explains how to do so. In this tutorial, we will introduce mesheryctl end-to-end testing using Bash Automating Testing System (BATS).
Understand Meshery ecosystem
The best advice that we can share is first of all, be familiarized with Meshery ecosystem, this is the key to be able to implement tests.
Be familiar with the different components and concepts in Meshery’s world, this can be done by reading the official documentation where you will find detailed explanations of the both architectural and logical concepts.
mesheryctl is Meshery’s CLI
Meshery CLI is written in Golang built on the Cobra framework and interacts with Meshery Server’s REST API. By creating end-to-end tests during the development lifecycle, it ensures that changes or new features are behaving as expected.
How to create a test
Before starting, be sure you read the contributing guide that will provide you the requirements and the implementation standards here.
Scenario
We will use a fictitious command named awesome through this tutorial that has 3 subcommands create, list and view that need to be tested. Now, let’s define how they should behave to implement the test.
Subcommands behavior expected:
-
create:
# Create `test` ~$ mesheryctl awesome create test test has been created successfully # Create missing argument ~$ mesheryctl awesome create Error: no name was provided. Please provide the name that you want to create -
list:
~$ mesheryctl awesome list Total number of elements: 3 Page: 1 NAME DESCRIPTION test description of test test-1 description of test 1 test-2 description of test 2 -
view:
# View `test` ~$ mesheryctl awesome view test Name: test # View missing argument ~$ mesheryctl awesome view Error: no name was provided. Please provide the name that you want to view # View no existing elements ~$ mesheryctl awesome view non-existing No element with name "non-existing" has been found. Ensure to provided an existing name. `mesheryctl awesome list` to list existing element.
All is set now to create required tests.
Folder structure
All End-To-End tests are stored in mesheryctl/tests/e2e
tests/
└── e2e
├── 000-prerequisites
├── 001-system
├── 002-model
├── 003-design
├── 004-perf
├── 005-component
└── helpers
8 directories
Implementation
You need to create a new folder that will contain all the tests for this command.
Following the implementation standard, the folder will be tests/e2e/006-awesome, then we will create a file for each subcommand, this is the expected result
tests/
└── e2e
├── 000-prerequisites
├── 001-system
├── 002-model
├── 003-design
├── 004-perf
├── 005-component
├── 006-awesome
│ ├── 00-awesome.bats
│ ├── 01-awesome-create.bats
│ ├── 02-awesome-list.bats
│ └── 03-awesome-view.bats
└── helpers
Create
Content of 01-awesome-create.bats
#!/usr/bin/env bats
# Add helpers functions to not reinvent the wheel
setup() {
load "$E2E_HELPERS_PATH/bats_libraries"
_load_bats_libraries
}
@test "create command without arguments fails" {
run $MESHERYCTL_BIN awesome create
assert_failure
assert_output --partial "Error: no name was provided."
assert_output --partial "Please provide the name that you want to create"
}
@test "create command with argument succeeds" {
run $MESHERYCTL_BIN awesome create test
assert_success
assert_output "Name: test"
}
List
Content of 02-awesome-list.bats
#!/usr/bin/env bats
# Add helpers functions to not reinvent the wheel
setup() {
load "$E2E_HELPERS_PATH/bats_libraries"
_load_bats_libraries
}
@test "list command succeeds" {
run $MESHERYCTL_BIN awesome list
assert_success
assert_output --partial Total number of elements: 3
assert_output --partial Page: 1
assert_output --partial NAME DESCRIPTION
assert_output --partial test description of test
assert_output --partial test-1 description of test 1
assert_output --partial test-2 description of test 2
}
View
Content of 03-awesome-view.bats
#!/usr/bin/env bats
# Add helpers functions to not reinvent the wheel
setup() {
load "$E2E_HELPERS_PATH/bats_libraries"
_load_bats_libraries
}
@test "view command without arguments fails" {
run $MESHERYCTL_BIN awesome view
assert_failure
assert_output --partial "Error: no name was provided."
assert_output --partial "Please provide the name that you want to view"
}
@test "view command with existing awesome name is displaying name" {
run $MESHERYCTL_BIN awesome view test
assert_success
assert_output "Name: test"
}
@test "view command with non-existing awesome name is displaying non existing message" {
run $MESHERYCTL_BIN awesome view non-existing
assert_success
assert_output --partial "No element with name "non-existing" has been found."
assert_output --partial "Ensure to provide an existing name. `mesheryctl awesome list` to list existing element."
}
Run added End-To-End tests
Now you have created a new suite of tests, you can confirm it is working as expected by running the following command and see an example of output
~/mesheryctl/ $ make e2e-no-build BATS_FOLDER_PATTERN=006-awesome
#### MESHERYCTL END-TO-END TESTING - START ####
00-awesome.bats
01-awesome-create.bats
✓ create command without arguments fails
✓ create command with argument succeed
02-awesome-list.bats
✓ list command succeed
03-awesome-view.bats
✓ view command without arguments fails
✓ view command with existing awesome name is displaying name
✓ view command with non-existing awesome name is displaying non existing message
6 tests, 0 failures
#### MESHERYCTL END-TO-END TESTING - DONE ####
Conclusion
You now have a small, repeatable e2e test suite for your imaginary awesome command. Practice:
- keep tests small and independent,
- use the helpers to avoid duplication,
- prefer deterministic assertions (exact when possible, partial when needed),
- and run them locally before pushing so CI stays happy.
If a test fails: write a better assertion, fix the bug, or add a regression test. Rinse and repeat.
Happy testing — may your CI logs be short and your green checks plentiful.