{"id":13550490,"url":"https://github.com/fzyzcjy/flutter_convenient_test","last_synced_at":"2026-01-08T16:22:27.943Z","repository":{"id":39906179,"uuid":"488137067","full_name":"fzyzcjy/flutter_convenient_test","owner":"fzyzcjy","description":"Write and debug tests easily, with full action history, time travel, screenshots, rapid re-execution, video records, interactivity, isolation and more","archived":false,"fork":false,"pushed_at":"2025-02-20T00:53:32.000Z","size":35987,"stargazers_count":514,"open_issues_count":1,"forks_count":45,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-14T11:12:37.932Z","etag":null,"topics":["dart","flutter","framework","test","testing"],"latest_commit_sha":null,"homepage":"pub.dev/packages/convenient_test","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fzyzcjy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-05-03T08:50:02.000Z","updated_at":"2025-04-08T17:21:59.000Z","dependencies_parsed_at":"2023-02-16T13:15:53.319Z","dependency_job_id":"8322f1f6-b976-4533-b4e0-91e51db39fb4","html_url":"https://github.com/fzyzcjy/flutter_convenient_test","commit_stats":{"total_commits":1151,"total_committers":24,"mean_commits":"47.958333333333336","dds":"0.16507384882710685","last_synced_commit":"13b555e0f17921cae2f5940330f850d6b70d265e"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fzyzcjy%2Fflutter_convenient_test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fzyzcjy%2Fflutter_convenient_test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fzyzcjy%2Fflutter_convenient_test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fzyzcjy%2Fflutter_convenient_test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fzyzcjy","download_url":"https://codeload.github.com/fzyzcjy/flutter_convenient_test/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254283336,"owners_count":22045140,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dart","flutter","framework","test","testing"],"created_at":"2024-08-01T12:01:33.863Z","updated_at":"2026-01-08T16:22:27.896Z","avatar_url":"https://github.com/fzyzcjy.png","language":"Dart","funding_links":[],"categories":["Dart","Frameworks"],"sub_categories":["Testing"],"readme":"# [flutter_convenient_test](https://github.com/fzyzcjy/flutter_convenient_test)\n\n[![Flutter Package](https://img.shields.io/pub/v/convenient_test.svg)](https://pub.dev/packages/convenient_test)\n[![CI](https://github.com/fzyzcjy/flutter_convenient_test/actions/workflows/ci.yaml/badge.svg)](https://github.com/fzyzcjy/flutter_convenient_test/actions/workflows/ci.yaml)\n[![Post-release](https://github.com/fzyzcjy/flutter_convenient_test/actions/workflows/post_release.yaml/badge.svg)](https://github.com/fzyzcjy/flutter_convenient_test/actions/workflows/post_release.yaml)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/45204254806b4790a2d6403b81156e42)](https://app.codacy.com/gh/fzyzcjy/flutter_convenient_test?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=fzyzcjy/flutter_convenient_test\u0026utm_campaign=Badge_Grade_Settings)\n\nWrite and debug tests easily, with full action history, time travel, screenshots, rapid re-execution, video records, retryability, interactivity, isolation and more.\n\n## 🚀 Advantages\n\n* **Enjoy 5x speedup**: Able to execute your tests not only on simulator/device, but also on host computer (much faster), without changing any code.\n* **Full action history**: Gain insight on what has happened to the tests - View all actions/assertions taken in the tests, with friendly descriptions.\n* **Time travel, with screenshots**: What did the UI look like when that button was tapped 50 steps ago? Now you know everything\n* **Rapid re-execution**: Edit code, save, run - done within seconds, not minutes.\n* **Videos recorded**: Watch what has happened, in full detail.\n* **Retryability**: No manual `pump`, wait or retry anymore. Just write down what you want, and the framework will retry and wait.\n* **Being interactive**: Play with the app interactively, again within seconds.\n* **Isolated**: One test will no longer destroy environment of other tests - run each with full isolation (optional feature).\n* **Abundant information for errors**: When something is not working, it tries to print out as much information as possible to help you quickly debug.\n* **Enhanced golden**: GUI to check golden changes, allow a few pixels to be different, screenshot widgets above your widget, etc (Standalone feature, does not require full convenient_test)\n* **Utilities**: Enter text without replacing, pump with run async, etc. (Standalone feature, does not require full convenient_test)\n\nAnd also...\n\n* **`integration_test` still there**: Freely use everything from `integration_test`, `mockito`,  `test`, etc.\n* **Flaky test awareness**: No false alarms, while no blindly ignoring.\n* **Suitable for CI**: Run headlessly, with logs to be visualized when needed. \n* **Miscellaneous**: Visually see target regions, run single test/group within seconds, raw logs...\n\n## 📷 Quick demo\n\n**NOTE**: The video only contains features up to 2022.05. New features not included in the video: The 5x speedup, the enhanced golden, etc.\n\n\u003c!--README_VIDEO_REPLACEMENT_PLACEHOLDER_ONE--\u003e\n\n\u003c!--README_VIDEO_REPLACEMENT_PLACEHOLDER_TWO--\u003e\n\nhttps://user-images.githubusercontent.com/5236035/167066810-d0aa36ba-0113-4140-92f9-cec0a9e77ed1.mov\n\n## Stability\n\nIt has been used extensively in my own 200kloc Flutter app in production environment, and I integrate it with my CI infra so it is run everyday.\n\nP.S. Surely, this package - especially the doc - is not yet perfect. If having problems, just [create an issue](https://github.com/fzyzcjy/flutter_convenient_test/issues) and I usually reply quite quickly.\n\n## Unreleased features\n\nI have been using these components internally for a long time, but have not found time to make cleanup (e.g. remove internal dependencies) in order to open-source it. If you like it, feel free to tell me and I will prioritize it!\n\n* Monkey tester: Randomly interact with tappable/draggable/... regions of your app, trying to find crashes. I even find [a bug](https://github.com/flutter/flutter/pull/128114) of Flutter *itself* using this simple monkey!\n* Benchmark helper: Using one command to automatically benchmark on all devices, upload to storage, and generate reports. (I run it in pseudo-CI and read the reports to see performance regressions.)\n\n## 📚 Features\n\n### 5x speedup \u0026 remove mobile devices\n\nIn addition to the standard way of integration tests, i.e. run them on a real mobile device / a simulator, this package supports running the exact same testing code on your host computer (Windows/MacOS/Linux) with similar experience.\n\nThis leads to a big speedup and reduction of needed resources. As we all know, running code on simulators / real devices are slow, and hard to parallelize as well. Running on host computer, on the other hand, does not have this problem.\n\n\u003csup\u003e\u003csub\u003eRemark: In my own app in production, it is \u003e10x faster, but without creating public and reproducible tests, I do not want to claim such a big improvement - so test by youself and see how fast it provides :)\u003c/sub\u003e\u003c/sup\u003e\n\nHow to use it: Just write code normally, and execute your code *as if* it is a widget test. If you see weird fonts, you may want [loadAppFonts](https://pub.dev/packages/golden_toolkit#loading-fonts).\n\n\u003cbr\u003e\n\n### Full action history\n\n\u003e See actions/taps/assertions taken in the tests, with friendly descriptions (in the left panel)\n\n![](https://raw.githubusercontent.com/fzyzcjy/flutter_convenient_test/master/doc/gif/a_action_history.gif)\n\n\u003cbr\u003e\n\n### Time travel with screenshots\n\n\u003e Tap an action to see its screenshots\n\n![](https://raw.githubusercontent.com/fzyzcjy/flutter_convenient_test/master/doc/gif/b_time_travel_screenshot.gif)\n\nP.S. Use mouse wheels and dragging to zoom and pan the screenshots.\n\nP.S. The gif is outdated - new version has (1) an overview of all screenshots (2) a ruler for each screenshot.\n\n\u003cbr\u003e\n\n### Rapid re-execution\n\n\u003e Edit code, save, run - within seconds\n\n![](https://raw.githubusercontent.com/fzyzcjy/flutter_convenient_test/master/doc/gif/c_rapid_execute.gif)\n\n\u003cbr\u003e\n\n### Videos recorded\n\n\u003e Watch what has happened in full detail (in right panel)\n\n![](https://raw.githubusercontent.com/fzyzcjy/flutter_convenient_test/master/doc/gif/d_video_record.gif)\n\nP.S. Highlighted action is in sync with the playing video. Tap action to seek video.\n\n\u003cbr\u003e\n\n### Being interactive\n\n\u003e Temporarily play with the app, interactively. (Flutter originally cannot interact with app in test mode)\n\n![](https://raw.githubusercontent.com/fzyzcjy/flutter_convenient_test/master/doc/gif/e_interactive.gif)\n\n\u003cbr\u003e\n\n### Retryability\n\nNo manual `pump`, wait or retry anymore. Just write down what you want, and the framework will retry and wait.\n\nExample:\n\n```dart\nawait t.get(find.byTooltip('Fetch Data From Backend')).tap();\n// OK even if \"fetch data\" needs undeterministic time interval. Will automatically pump, wait and retry.\nawait t.get(find.text('New Data')).should(findsOneWidget);\n```\n\nMore in quickstart and tutorials below.\n\n### Isolation mode\n\nOne test will no longer destroy environment of other tests - now you can run run each with full isolation.\n\nThis is especially helpful in big projects (such as mine), when an end-to-end setup is not easy to tear down, and one failed test can cause all subsequent tests to have damaged execution environment and thus fail.\n\nTechnical details: If this mode is enabled, a hot restart will be performed after each attempt of each test.\n\n### Abundant information for errors\n\nWhen something is not working, it tries to print out as much information as possible to help you quickly debug.\n\nFor example, suppose you provide a `finder` that accidentally matches two widgets. Then, convenient_test will tell you the location of each widget, as well as a chain of render objects. Together with the screenshots/videos it provides, the finder problem can be fixed easily.\n\n\u003csup\u003e\u003csub\u003eRemark: The GIFs are outdated and does not show this feature.\u003c/sub\u003e\u003c/sup\u003e\n\n### Enhanced golden\n\nThis is a standalone feature, i.e. you can use it without using convenient_test.\n\n#### Golden overview GUI\n\nIt is a simple GUI to list and check all golden differences, with interactivity like pan and zoom. I personally use it daily as follows: After changing a feature, I run all regression tests. Then, if some tests report a golden change, I look at this page to check whether the change is intended or a bug.\n\nTo enter this page, tap the \"golden\" button at the top of homepage.\n\n#### Golden utilities\n\n* **Allow a few pixels to be different**: Flutter's builtin golden test requires every pixel to be exactly the same. I often see cases when the golden screenshot is the \"same\" from human eyes, but is marked as failed because of non-perceptable differences. This feature allows you to configure amount of toleration to avoid that. (`GoldenConfig.maxToleration`, `GoldenConfig.greaterThanToleration`)\n* **Crop a part of widget** / **Screenshot widgets above your widget**: For example, suppose you have a button with a hint bubble, implemented by [flutter_portal](https://github.com/fzyzcjy/flutter_portal) or `Overlay`. Then, if you golden by `find.byKey(yourButton)`, you will not screen the hint bubble as well. By using this `cropBbox` feature, you can take a screenshot of the *whole* screen, and crop the parts (the button) you want. (`GoldenConfig.cropBbox`)\n* **Forbid updating local files**: Useful when your file is generated from elsewhere (e.g. another line of code), and you never want to update it even with `--update-goldens`. (`GoldenConfig.allowUpdate`)\n* When a golden assertion fails, its image details will be also shown in the manager panel.\n\n#### Quickstart example\n\n```dart\ngoldenFileComparator = EnhancedLocalFileComparator.configFromCurrent(); // setup\n\n// just like the old way, except that we call `EnhancedLocalFileComparator.createUri` with extra configurations\nfinal config = GoldenConfig(...);\nawait expectLater(whatever, matchesGoldenFile(EnhancedLocalFileComparator.createUri('something.png', config)));\n```\n\n\u003c!--[TODO screenshot]--\u003e\n\n### Utilities\n\n* Enter text without replacing (`enterTextWithoutReplace`): The standard `enterText` replaces the old content, making it inconvenient if we want to append some text - which is the normal behavior of humans.\n* Pump with run async (`runAsyncAndPumpUntil`, `pumpAndSettleWithRunAsync`, etc): If your code does something that needs \"real\" async, a simple `pumpAndSettle` will not work, so this function is created.\n\n### `integration_test` is still there\n\nYou can still use everything from `integration_test`, `mockito`,  `test`, etc. This package is not a reinvented wheel, and has exposed the underlying `integration_test` to you.\n\nIf you want to migrate to this package from raw `integration_test`, have a look at Getting Started section below.\n\n### Flaky tests awareness\n\nFlaky is flaky, and we are aware of it. It is neither failed nor success, so you will not be alarmed by false positives, and not completely ignore it.\n\n\u003c!--[TODO screenshot: Several tests, one failed, one flaky, one success]--\u003e\n\n### CI / headless mode\n\n[`packages/convenient_test_manager_dart`](packages/convenient_test_manager_dart) runs without GUI \nand only produce log data and exit code, making it suitable to be run in a CI.\nSimply use `convenient_test_manager_dart` instead of `convenient_test_manager`.\nSee [Run the `manager`](#run-the-manager) and [Getting started](#getting-started).\n\n```sh\n# in one shell\nconvenient_test_manager_dart\n# in another shell, run your worker app\nflutter run integration_test/main_test.dart --host-vmservice-port 9753 --disable-service-auth-codes --dart-define \"CONVENIENT_TEST_APP_CODE_DIR=$PWD\"\n```\n\n### Reports\n\nIf you want to examine the details with GUI, just open the generated artifact in the GUI using `Load Report` button.\n\nBy default the manager will save reports to a temporary directory. Typically:\n\n- macOS: `$HOME/Library/Caches/ConvenientTest`\n- Linux: `/tmp/ConvenientTest`\n- Windows: `%LocalAppData%\\Temp\\ConvenientTest`\n\nUse `--report-save-path /some/path` (or `--dart-define \"CONVENIENT_MANAGER_REPORT_SAVE_PATH=/some/path\"`) to change this.\n\n#### Format\n\nThe reports are exported using [protobuf](https://protobuf.dev/).\nSee the schema at [`convenient_test.proto`](packages/convenient_test_common_dart/proto/convenient_test.proto).\n\n### Run single test/group\n\nTap \"Run\" icon button after each test or group to re-run *only* that test/group, without running anything else. All within seconds - no need to recompile like what the original test package did.\n\n### Visually see target regions\n\nUseful when replaying videos and screenshots\n\n* `Mark`s have colored borders\n* Gestures have visual feedbacks\n\n### Raw logs\n\nTap \"Raw Logs\" in the right panel to see raw outputs of a test.\n\n### Header panel\n\nFollowing is a brief description of the functionalities of each button in the header panel.\n\n* Run All: Run all tests below\n* Halt: Stop the currently running worker\n* Interactive Mode: Enter \"interactive mode\" (described above)\n* Reload Info: Reload test metadata such as the group names and test names\n* Reconnect VM: Connect to the Dart VM of the worker app\n* Load Report: Load and display a report generated when `SaveReport` toggle is enabled or run within CI/headless mode\n* Golden Diff Page: Enter the golden diff page (described above)\n\nFollowing are about the toggles:\n\n* Isolation: Whether to enable \"isolation mode\" (described above)\n* UpdateGoldens: Whether to update the golden files on the disk, similar to `--update-goldens` flag in a traditional Flutter test\n* Retry: When a test fails, whether to retry (and mark as flaky), or directly mark it failed\n* SaveReport: Whether to save logs to a report file, such that it can be visualized later via \"Load Report\"\n* Hover: When hovering the action log panel, whether highlight the hovered entry and immediately show related information\n* AutoJump: Whether to jump to newly received action entries\n* AutoExpand: Whether to expand and collapse automatically for the newly received test and action entries\n\n## Tutorial: Run examples\n\n1. Clone this repository and enter the `packages/convenient_test/example` folder.\n2. Run the example app (e.g. using iOS simulator) via: \n   ```sh\n   flutter run integration_test/main_test.dart --host-vmservice-port 9753 --disable-service-auth-codes --dart-define \"CONVENIENT_TEST_APP_CODE_DIR=$PWD\"\n   ```\n   Can also be run via VSCode or Android Studio with similar commands.\n3. Run the GUI located in `packages/convenient_test_manager`. (See details in section below)\n4. Enjoy the GUI!\n\n## Getting started\n\n1. (Optional but recommended) Navigate to the flutter home directory and apply [this patch](doc/patches/flutter/get-running-async-tasks.diff):\n   `cd $FLUTTER_HOME \u0026\u0026 curl https://raw.githubusercontent.com/fzyzcjy/flutter_convenient_test/master/doc/patches/flutter/get-running-async-tasks.diff | git apply`\n   - While this is not strictly necessary, it is recommended to improve scenarios when running multiple async tasks. see [#337](https://github.com/fzyzcjy/flutter_convenient_test/issues/337) for more information\n2. Navigate to your project dir and run `flutter pub add convenient_test dev:convenient_test_dev`\n   - or manually update your `pubspec.yaml` to include `convenient_test: ^1.0.0` in the `dependencies` section, and `convenient_test_dev: ^1.0.0` in the `dev_dependencies` section. As normal, we need to `flutter pub get`.\n3. Create `integration_test/main_test.dart` file in your app. Fill it like `void main() =\u003e convenientTestMain(MyConvenientTestSlot(), () { ... the normal test code you write });`. See the example [`main_test.dart`](packages/convenient_test/example/integration_test/main_test.dart) for demonstration.\n4. Run your app (e.g. using iOS simulator) via `flutter run integration_test/main_test.dart --host-vmservice-port 9753 --disable-service-auth-codes --dart-define \"CONVENIENT_TEST_APP_CODE_DIR=$PWD\"`. Can also be run via VSCode or Android Studio with similar commands.\n   - for use with the Android emulator, add `--dart-define CONVENIENT_TEST_MANAGER_HOST=10.0.2.2`\n5. Run the Convenient Test Manager (See details in section below)\n\n### Run the `manager`\n\n- [`packages/convenient_test_manager`](packages/convenient_test_manager) is a flutter GUI app that allows running and inspecting individual tests.\n  Use this for development and debugging.\n- [`packages/convenient_test_manager_dart`](packages/convenient_test_manager_dart) is a dart CLI app that runs all tests and terminates with a corresponding exit code.\n  Use this for CI and automated testing. See [CI / headless mode](#ci--headless-mode)\n\n#### Method 1: Download precompiled binary\n\nSee [Releases](https://github.com/fzyzcjy/flutter_convenient_test/releases) for binaries.\n\nAdditionally, there are precompiled binaries for each commit, at the \"artifacts\" section in [the CI page](https://github.com/fzyzcjy/flutter_convenient_test/actions/workflows/ci.yaml)\n(download only available for logged in GitHub users).\nFor example, go to the most recent _CI_ run, download `manager_gui_macos` artifact, unzip it, and open it.\n\n#### Method 2: `flutter run` / `flutter build`\n\nThe GUI and CLI managers are just flutter and dart projects as well, respectively.\nSo they can be run and built in the same way one would with any other flutter or dart project:\n\nCheck the requirements for developing flutter desktop apps for\n[macOS](https://docs.flutter.dev/platform-integration/macos/install-macos/install-macos-from-ios),\n[Linux](https://docs.flutter.dev/platform-integration/linux/install-linux/install-linux-from-android),\nand [Windows](https://docs.flutter.dev/platform-integration/windows/install-windows/install-windows-from-android). Then:\n\n```sh\ngit clone https://github.com/fzyzcjy/flutter_convenient_test.git\ncd flutter_convenient_test/packages/convenient_test_manager\n\n# compile executable. platform = linux | macos | windows\nflutter build \u003cplatform\u003e\n# or just run directly\nflutter run -d \u003cplatform\u003e\n```\n\nFor CLI manager:\n\n```sh\ncd flutter_convenient_test/packages/convenient_test_manager\n\ndart compile exe bin/convenient_test_manager_dart.dart\n# or just run directly\ndart run\n```\n\n#### Method 3: `dart pub global` (only CLI manager)\n\nSet up once (re-run to update):\n\n```sh\ndart pub global activate --source git https://github.com/fzyzcjy/flutter_convenient_test.git --git-path packages/convenient_test_manager_dart\n```\n\n\u003e [!TIP]\n\u003e Add `--git-ref v1.x.x` to `dart pub global activate` to check out a specific [release](https://github.com/fzyzcjy/flutter_convenient_test/releases).\n\nRun using:\n\n```sh\ndart pub global run convenient_test_manager_dart\n```\n\n## Miscellaneous\n\n### Configuration\n\nThere are a few ways to configure the manager:\n\n1. From `$HOME/.config/convenient_test.json`.\n2. From various environment variables.\n3. From command line arguments (when run via `convenient_test_manager_dart` command line)\n4. Change configurations via GUI (e.g. switches at right-top)\n\nFor all options that are configurable and all environment variable names, please see \n\n- [`consts.dart`](packages/convenient_test_common_dart/lib/src/consts.dart)\n- [`static_config.dart`](packages/convenient_test_dev/lib/src/support/static_config.dart)\n- [`global_config_store.dart`](packages/convenient_test_manager_dart/lib/stores/global_config_store.dart) only manager related options\n\n(By doing so you can always see the up-to-date information and there is no possibility to see outdated doc.)\n\nIf you are trying to use this package with Android Virtual Emulator (AVD), you may need to set `kConvenientTestManagerHost` to `10.0.2.2` (add `--dart-define CONVENIENT_TEST_MANAGER_HOST=10.0.2.2`) because of its [network topology](https://stackoverflow.com/questions/9808560/why-do-we-use-10-0-2-2-to-connect-to-local-web-server-instead-of-using-computer). Please see [issue #253](https://github.com/fzyzcjy/flutter_convenient_test/issues/253) for more details.\n\n### Limitations\n\n1. `Video replaying` feature is not yet implemented in Android (but feel free to PR!).\n\n## Q\u0026A\n\n### `pumpWithRunAsyncUntil` timed out\n\nOne thing to check is whether there are infinite animations. For example, setting `EditableText.debugDeterministicCursor = true` can avoid cursor blinking forever.\n\n## Contributors\n\nFor detailed PRs (excluding myself), please see [this link](https://github.com/fzyzcjy/flutter_convenient_test/pulls?q=is%3Apr+-author%3Afzyzcjy+).\n\n\u003c!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section --\u003e\n[![All Contributors](https://img.shields.io/badge/all_contributors-16-orange.svg?style=flat-square)](#contributors-)\n\u003c!-- ALL-CONTRIBUTORS-BADGE:END --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section --\u003e\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/Rohithgilla12\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/19389850?v=4?s=100\" width=\"100px;\" alt=\"Rohith Gilla\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRohith Gilla\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=Rohithgilla12\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://mehrankordi.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1547111?v=4?s=100\" width=\"100px;\" alt=\"Mehran Kordi\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMehran Kordi\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=MCord\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ethancadoo\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/100008135?v=4?s=100\" width=\"100px;\" alt=\"ethancadoo\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eethancadoo\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=ethancadoo\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=ethancadoo\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://vhanda.in\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/426467?v=4?s=100\" width=\"100px;\" alt=\"Vishesh Handa\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eVishesh Handa\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=vHanda\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ostk0069\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/27538852?v=4?s=100\" width=\"100px;\" alt=\"Takuma Osada\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eTakuma Osada\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=ostk0069\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/ronba\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/10216856?v=4?s=100\" width=\"100px;\" alt=\"ronba\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eronba\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=ronba\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://pacia.tech\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/40357511?v=4?s=100\" width=\"100px;\" alt=\"Bartek Pacia\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBartek Pacia\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=bartekpacia\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://blog.alexv525.com\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/15884415?v=4?s=100\" width=\"100px;\" alt=\"Alex Li\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eAlex Li\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=AlexV525\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/getBoolean\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/19920697?v=4?s=100\" width=\"100px;\" alt=\"getBoolean\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003egetBoolean\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=getBoolean\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/gilice\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/104317939?v=4?s=100\" width=\"100px;\" alt=\"gilice\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003egilice\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=gilice\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/madmini\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/26089559?v=4?s=100\" width=\"100px;\" alt=\"Max Jakobitsch\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMax Jakobitsch\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=madmini\" title=\"Code\"\u003e💻\u003c/a\u003e \u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=madmini\" title=\"Documentation\"\u003e📖\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://keybase.io/jmatth\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1316184?v=4?s=100\" width=\"100px;\" alt=\"Josh Matthews\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eJosh Matthews\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=jmatth\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://gnunicorn.org\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/40496?v=4?s=100\" width=\"100px;\" alt=\"Benjamin Kampmann\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eBenjamin Kampmann\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=gnunicorn\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/meltzow\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/1238001?v=4?s=100\" width=\"100px;\" alt=\"Mario Meltzow\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eMario Meltzow\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=meltzow\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/lunakoan\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/119916943?v=4?s=100\" width=\"100px;\" alt=\"Luna\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eLuna\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=lunakoan\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n      \u003ctd align=\"center\" valign=\"top\" width=\"14.28%\"\u003e\u003ca href=\"https://github.com/lehmannk\"\u003e\u003cimg src=\"https://avatars.githubusercontent.com/u/36925534?v=4?s=100\" width=\"100px;\" alt=\"Kai Lehmann\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eKai Lehmann\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003cbr /\u003e\u003ca href=\"https://github.com/fzyzcjy/flutter_convenient_test/commits?author=lehmannk\" title=\"Code\"\u003e💻\u003c/a\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c!-- markdownlint-restore --\u003e\n\u003c!-- prettier-ignore-end --\u003e\n\n\u003c!-- ALL-CONTRIBUTORS-LIST:END --\u003e\n\nThanks for testing frameworks in JavaScript, especially `Cypress`, for giving inspirations!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffzyzcjy%2Fflutter_convenient_test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffzyzcjy%2Fflutter_convenient_test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffzyzcjy%2Fflutter_convenient_test/lists"}