diff --git a/CHANGELOG.md b/CHANGELOG.md index ffdfcdf..4f47bd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [1.1.9] - 24/11/2020 +* Fixes #93 & #92 - Error waiting for no transient callbacks from Flutter driver +* Added option to leave Flutter app under test running when the tests finish see `keepAppRunningAfterTests` configuration property +* Added the ability to have multiple example blocks with tags per scenario outline + ## [1.1.8+9] - 20/09/2020 * Fixes #84 - pre-defined `present within N seconds` is limited by system timeout (thanks @doubleo2) diff --git a/README.md b/README.md index 3ef60bd..685aed2 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ Available as a Dart package https://pub.dartlang.org/packages/flutter_gherkin + [Steps Definitions](#steps-definitions) - [Given](#given) - [Then](#then) + - [Expects Assertions](#expects-assertions) - [Step Timeout](#step-timeout) - [Multiline Strings](#multiline-strings) - [Data tables](#data-tables) @@ -484,6 +485,11 @@ This should point to the *testable* application that enables the Flutter driver Defaults to `true` This optional argument lets you specify if the target application should be built prior to running the first test. This defaults to `true` +#### keepAppRunningAfterTests + +Defaults to `false` +This optional argument will keep the Flutter application running when done testing. This defaults to `false` + #### buildFlavor Defaults to empty string @@ -580,7 +586,9 @@ StepDefinitionGeneric ThenExpectAppleCount() { } ``` -**Caveat**: The `expect` library currently only works within the library's own `test` function blocks; so using it with a `Then` step will cause an error. Therefore, the `expectMatch` or `expectA` or `this.expect` methods have been added which mimic the underlying functionality of `except` in that they assert that the give is true. The `Matcher` within Dart's test library still work and can be used as expected. +#### Expects Assertions + +**Caveat**: The `expect` library currently only works within the library's own `test` function blocks; so using it with a `Then` step will cause an error. Therefore, the `expectMatch` or `expectA` or `this.expect` or `context.expect` methods have been added which mimic the underlying functionality of `except` in that they assert that the give is true. The `Matcher` within Dart's test library still work and can be used as expected. #### Step Timeout diff --git a/example/test_driver/app_test.dart b/example/test_driver/app_test.dart index 9af77ae..98126f4 100644 --- a/example/test_driver/app_test.dart +++ b/example/test_driver/app_test.dart @@ -29,7 +29,7 @@ Future main() { ..targetAppPath = 'test_driver/app.dart' // ..buildFlavor = "staging" // uncomment when using build flavor and check android/ios flavor setup see android file android\app\build.gradle // ..targetDeviceId = "all" // uncomment to run tests on all connected devices or set specific device target id - // ..tagExpression = '@smoke' // uncomment to see an example of running scenarios based on tag expressions + // ..tagExpression = '@smoke and not @ignore' // uncomment to see an example of running scenarios based on tag expressions // ..logFlutterProcessOutput = true // uncomment to see command invoked to start the flutter test app // ..verboseFlutterProcessLogs = true // uncomment to see the verbose output from the Flutter process // ..flutterBuildTimeout = Duration(minutes: 3) // uncomment to change the default period that flutter is expected to build and start the app within diff --git a/example/test_driver/report.json b/example/test_driver/report.json index 7d1d6e6..fe282cc 100644 --- a/example/test_driver/report.json +++ b/example/test_driver/report.json @@ -1 +1 @@ -[{"description":"","id":"counter","keyword":"Feature","line":2,"name":"Counter","uri":".\\features\\counter_increases_french.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":5,"steps":[{"keyword":"Etant ","name":"donné que I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_french.feature:6"},"result":{"status":"passed","duration":48000000}},{"keyword":"Et ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_french.feature:7"},"result":{"status":"passed","duration":121000000}},{"keyword":"Quand ","name":"I tap the \"increment\" button 10 times","line":8,"match":{"location":".\\features\\counter_increases_french.feature:8"},"result":{"status":"passed","duration":2578000000}},{"keyword":"Alors ","name":"I expect the \"counter\" to be \"10\"","line":9,"match":{"location":".\\features\\counter_increases_french.feature:9"},"result":{"status":"passed","duration":43000000}}]}]},{"description":"","id":"interaction","keyword":"Feature","line":1,"name":"Interaction","uri":".\\features\\long_press_widget.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"interaction;widget can be long pressed","name":"Widget can be long pressed","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"longPressText\" to be \"Text that has not been long pressed\"","line":4,"match":{"location":".\\features\\long_press_widget.feature:4"},"result":{"status":"passed","duration":70000000}},{"keyword":"When ","name":"I long press the \"longPressText\" text","line":5,"match":{"location":".\\features\\long_press_widget.feature:5"},"result":{"status":"passed","duration":895000000}},{"keyword":"Then ","name":"I expect the \"longPressText\" to be \"Text has been long pressed!\"","line":6,"match":{"location":".\\features\\long_press_widget.feature:6"},"result":{"status":"passed","duration":36000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":4,"steps":[{"keyword":"Given ","name":"I pick the colour red","line":5,"match":{"location":".\\features\\counter_increases.feature:5"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":6,"match":{"location":".\\features\\counter_increases.feature:6"},"result":{"status":"passed","duration":42000000}},{"keyword":"When ","name":"I tap the \"increment\" button 10 times","line":7,"match":{"location":".\\features\\counter_increases.feature:7"},"result":{"status":"passed","duration":2543000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"10\"","line":8,"match":{"location":".\\features\\counter_increases.feature:8"},"result":{"status":"passed","duration":31000000}}]}]},{"description":"","id":"delayed navigation","keyword":"Feature","line":1,"name":"Delayed navigation","uri":".\\features\\counter_increases_slowly.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"delayed navigation;user can navigate to page two. eventually","name":"User can navigate to page two. Eventually","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\counter_increases_slowly.feature:4"},"result":{"status":"passed","duration":46000000}},{"keyword":"When ","name":"I long press the \"openPage2\" button","line":5,"match":{"location":".\\features\\counter_increases_slowly.feature:5"},"result":{"status":"passed","duration":784000000}},{"keyword":"Then ","name":"I expect the widget \"pageTwo\" to be present within 15 seconds","line":6,"match":{"location":".\\features\\counter_increases_slowly.feature:6"},"result":{"status":"passed","duration":12158000000}}]}]},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\app_restart.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;counter should reset when app is restarted","name":"counter should reset when app is restarted","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\app_restart.feature:4"},"result":{"status":"passed","duration":44000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":5,"match":{"location":".\\features\\app_restart.feature:5"},"result":{"status":"passed","duration":348000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":6,"match":{"location":".\\features\\app_restart.feature:6"},"result":{"status":"passed","duration":35000000}},{"keyword":"When ","name":"I restart the app","line":7,"match":{"location":".\\features\\app_restart.feature:7"},"result":{"status":"passed","duration":2627000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"0\"","line":8,"match":{"location":".\\features\\app_restart.feature:8"},"result":{"status":"passed","duration":44000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\sub-features\\counter_increases.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":5,"tags":[{"line":4,"name":"@perf"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":6,"match":{"location":".\\features\\sub-features\\counter_increases.feature:6"},"result":{"status":"passed","duration":44000000}},{"keyword":"When ","name":"I tap the \"increment\" button 20 times","line":7,"match":{"location":".\\features\\sub-features\\counter_increases.feature:7"},"result":{"status":"passed","duration":4945000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"20\"","line":8,"match":{"location":".\\features\\sub-features\\counter_increases.feature:8"},"result":{"status":"passed","duration":28000000}}]}]},{"description":"","id":"custom parameter example","keyword":"Feature","line":1,"name":"Custom Parameter Example","uri":".\\features\\custom_parameter_example.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"custom parameter example;custom colour parameter","name":"Custom colour parameter","description":"","line":4,"steps":[{"keyword":"Given ","name":"I pick the colour red","line":5,"match":{"location":".\\features\\custom_parameter_example.feature:5"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I pick the colour green","line":6,"match":{"location":".\\features\\custom_parameter_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I pick the colour blue","line":7,"match":{"location":".\\features\\custom_parameter_example.feature:7"},"result":{"status":"passed","duration":0}}]}]},{"description":"","id":"drawer","keyword":"Feature","line":1,"name":"Drawer","uri":".\\features\\drawer.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"drawer;should open the drawer","name":"should open the drawer","description":"","line":3,"steps":[{"keyword":"Given ","name":"I open the drawer","line":4,"match":{"location":".\\features\\drawer.feature:4"},"result":{"status":"passed","duration":1461000000}},{"keyword":"Given ","name":"I close the drawer","line":5,"match":{"location":".\\features\\drawer.feature:5"},"result":{"status":"passed","duration":408000000}}]}]},{"description":"","id":"navigation","keyword":"Feature","line":1,"name":"Navigation","uri":".\\features\\back_navigation.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"navigation;user can navigate back from page two","name":"User can navigate back from page two","description":"","line":4,"tags":[{"line":3,"name":"@debug"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":5,"match":{"location":".\\features\\back_navigation.feature:5"},"result":{"status":"passed","duration":42000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\back_navigation.feature:6"},"result":{"status":"passed","duration":338000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":7,"match":{"location":".\\features\\back_navigation.feature:7"},"result":{"status":"passed","duration":30000000}},{"keyword":"Given ","name":"I tap the label that contains the text \"Open page 2\"","line":9,"match":{"location":".\\features\\back_navigation.feature:9"},"result":{"status":"passed","duration":387000000}},{"keyword":"Then ","name":"I expect the text \"Contents of page 2\" to be present","line":10,"match":{"location":".\\features\\back_navigation.feature:10"},"result":{"status":"passed","duration":19000000}},{"keyword":"Given ","name":"I tap the back button","line":12,"match":{"location":".\\features\\back_navigation.feature:12"},"result":{"status":"passed","duration":375000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":13,"match":{"location":".\\features\\back_navigation.feature:13"},"result":{"status":"passed","duration":26000000}}]}]},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\counter.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;should increment counter","name":"should increment counter","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\counter.feature:4"},"result":{"status":"passed","duration":49000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":5,"match":{"location":".\\features\\counter.feature:5"},"result":{"status":"passed","duration":325000000}},{"keyword":"And ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\counter.feature:6"},"result":{"status":"passed","duration":263000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"2\"","line":7,"match":{"location":".\\features\\counter.feature:7"},"result":{"status":"passed","duration":28000000}}]},{"keyword":"Scenario","type":"scenario","id":"startup;counter should reset when app is restarted","name":"counter should reset when app is restarted","description":"","line":9,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":10,"match":{"location":".\\features\\counter.feature:10"},"result":{"status":"passed","duration":42000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":11,"match":{"location":".\\features\\counter.feature:11"},"result":{"status":"passed","duration":332000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":12,"match":{"location":".\\features\\counter.feature:12"},"result":{"status":"passed","duration":36000000}},{"keyword":"When ","name":"I restart the app","line":13,"match":{"location":".\\features\\counter.feature:13"},"result":{"status":"passed","duration":2568000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"0\"","line":14,"match":{"location":".\\features\\counter.feature:14"},"result":{"status":"passed","duration":47000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases_scenerio_outline_example.feature","elements":[{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 1)","name":"Counter increases when the button is pressed (Example 1)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":44000000}},{"keyword":"When ","name":"I tap the \"increment\" button 1 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":319000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":28000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 2)","name":"Counter increases when the button is pressed (Example 2)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":41000000}},{"keyword":"When ","name":"I tap the \"increment\" button 2 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":602000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"2\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":38000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 3)","name":"Counter increases when the button is pressed (Example 3)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":44000000}},{"keyword":"When ","name":"I tap the \"increment\" button 5 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":1302000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"5\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":25000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed (example 4)","name":"Counter increases when the button is pressed (Example 4)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":40000000}},{"keyword":"When ","name":"I tap the \"increment\" button 10 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":2523000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"10\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":26000000}}]}]}] \ No newline at end of file +[{"description":"","id":"custom parameter example","keyword":"Feature","line":1,"name":"Custom Parameter Example","uri":".\\features\\custom_parameter_example.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"custom parameter example;custom colour parameter","name":"Custom colour parameter","description":"","line":4,"steps":[{"keyword":"Given ","name":"I pick the colour red","line":5,"match":{"location":".\\features\\custom_parameter_example.feature:5"},"result":{"status":"passed","duration":14000000}},{"keyword":"Given ","name":"I pick the colour green","line":6,"match":{"location":".\\features\\custom_parameter_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I pick the colour blue","line":7,"match":{"location":".\\features\\custom_parameter_example.feature:7"},"result":{"status":"passed","duration":0}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases_scenerio_outline_example.feature","elements":[{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed examples: (1)","name":"Counter increases when the button is pressed Examples: (1)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":149000000}},{"keyword":"When ","name":"I tap the \"increment\" button 1 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":345000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":54000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed examples: (2)","name":"Counter increases when the button is pressed Examples: (2)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":47000000}},{"keyword":"When ","name":"I tap the \"increment\" button 2 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":570000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"2\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":28000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed examples: (3)","name":"Counter increases when the button is pressed Examples: (3)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":79000000}},{"keyword":"When ","name":"I tap the \"increment\" button 5 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":1307000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"5\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":33000000}}]},{"keyword":"Scenario Outline","type":"scenario","id":"counter;counter increases when the button is pressed examples: (4)","name":"Counter increases when the button is pressed Examples: (4)","description":"","line":5,"tags":[{"line":4,"name":"@scenario_outline"}],"steps":[{"keyword":"Given ","name":"I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:7"},"result":{"status":"passed","duration":46000000}},{"keyword":"When ","name":"I tap the \"increment\" button 10 times","line":8,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:8"},"result":{"status":"passed","duration":2546000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"10\"","line":9,"match":{"location":".\\features\\counter_increases_scenerio_outline_example.feature:9"},"result":{"status":"passed","duration":30000000}}]}]},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\counter.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;should increment counter","name":"should increment counter","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\counter.feature:4"},"result":{"status":"passed","duration":51000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":5,"match":{"location":".\\features\\counter.feature:5"},"result":{"status":"passed","duration":337000000}},{"keyword":"And ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\counter.feature:6"},"result":{"status":"passed","duration":274000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"2\"","line":7,"match":{"location":".\\features\\counter.feature:7"},"result":{"status":"passed","duration":30000000}}]},{"keyword":"Scenario","type":"scenario","id":"startup;counter should reset when app is restarted","name":"counter should reset when app is restarted","description":"","line":9,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":10,"match":{"location":".\\features\\counter.feature:10"},"result":{"status":"passed","duration":45000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":11,"match":{"location":".\\features\\counter.feature:11"},"result":{"status":"passed","duration":334000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":12,"match":{"location":".\\features\\counter.feature:12"},"result":{"status":"passed","duration":34000000}},{"keyword":"When ","name":"I restart the app","line":13,"match":{"location":".\\features\\counter.feature:13"},"result":{"status":"passed","duration":2591000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"0\"","line":14,"match":{"location":".\\features\\counter.feature:14"},"result":{"status":"passed","duration":44000000}}]}]},{"description":"","id":"delayed navigation","keyword":"Feature","line":1,"name":"Delayed navigation","uri":".\\features\\counter_increases_slowly.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"delayed navigation;user can navigate to page two. eventually","name":"User can navigate to page two. Eventually","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\counter_increases_slowly.feature:4"},"result":{"status":"passed","duration":41000000}},{"keyword":"When ","name":"I long press the \"openPage2\" button","line":5,"match":{"location":".\\features\\counter_increases_slowly.feature:5"},"result":{"status":"passed","duration":790000000}},{"keyword":"Then ","name":"I expect the widget \"pageTwo\" to be present within 15 seconds","line":6,"match":{"location":".\\features\\counter_increases_slowly.feature:6"},"result":{"status":"passed","duration":12151000000}}]}]},{"description":"","id":"startup","keyword":"Feature","line":1,"name":"Startup","uri":".\\features\\app_restart.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"startup;counter should reset when app is restarted","name":"counter should reset when app is restarted","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":4,"match":{"location":".\\features\\app_restart.feature:4"},"result":{"status":"passed","duration":42000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":5,"match":{"location":".\\features\\app_restart.feature:5"},"result":{"status":"passed","duration":348000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":6,"match":{"location":".\\features\\app_restart.feature:6"},"result":{"status":"passed","duration":41000000}},{"keyword":"When ","name":"I restart the app","line":7,"match":{"location":".\\features\\app_restart.feature:7"},"result":{"status":"passed","duration":2671000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"0\"","line":8,"match":{"location":".\\features\\app_restart.feature:8"},"result":{"status":"passed","duration":44000000}}]}]},{"description":"","id":"navigation","keyword":"Feature","line":1,"name":"Navigation","uri":".\\features\\back_navigation.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"navigation;user can navigate back from page two","name":"User can navigate back from page two","description":"","line":4,"tags":[{"line":3,"name":"@debug"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":5,"match":{"location":".\\features\\back_navigation.feature:5"},"result":{"status":"passed","duration":43000000}},{"keyword":"When ","name":"I tap the \"increment\" button","line":6,"match":{"location":".\\features\\back_navigation.feature:6"},"result":{"status":"passed","duration":326000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":7,"match":{"location":".\\features\\back_navigation.feature:7"},"result":{"status":"passed","duration":31000000}},{"keyword":"Given ","name":"I tap the label that contains the text \"Open page 2\"","line":9,"match":{"location":".\\features\\back_navigation.feature:9"},"result":{"status":"passed","duration":401000000}},{"keyword":"Then ","name":"I expect the text \"Contents of page 2\" to be present","line":10,"match":{"location":".\\features\\back_navigation.feature:10"},"result":{"status":"passed","duration":16000000}},{"keyword":"Given ","name":"I tap the back button","line":12,"match":{"location":".\\features\\back_navigation.feature:12"},"result":{"status":"passed","duration":387000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"1\"","line":13,"match":{"location":".\\features\\back_navigation.feature:13"},"result":{"status":"passed","duration":28000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\counter_increases.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":4,"steps":[{"keyword":"Given ","name":"I pick the colour red","line":5,"match":{"location":".\\features\\counter_increases.feature:5"},"result":{"status":"passed","duration":0}},{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":6,"match":{"location":".\\features\\counter_increases.feature:6"},"result":{"status":"passed","duration":44000000}},{"keyword":"When ","name":"I tap the \"increment\" button 10 times","line":7,"match":{"location":".\\features\\counter_increases.feature:7"},"result":{"status":"passed","duration":2529000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"10\"","line":8,"match":{"location":".\\features\\counter_increases.feature:8"},"result":{"status":"passed","duration":30000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":1,"name":"Counter","uri":".\\features\\sub-features\\counter_increases.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":5,"tags":[{"line":4,"name":"@perf"}],"steps":[{"keyword":"Given ","name":"I expect the \"counter\" to be \"0\"","line":6,"match":{"location":".\\features\\sub-features\\counter_increases.feature:6"},"result":{"status":"passed","duration":42000000}},{"keyword":"When ","name":"I tap the \"increment\" button 20 times","line":7,"match":{"location":".\\features\\sub-features\\counter_increases.feature:7"},"result":{"status":"passed","duration":4977000000}},{"keyword":"Then ","name":"I expect the \"counter\" to be \"20\"","line":8,"match":{"location":".\\features\\sub-features\\counter_increases.feature:8"},"result":{"status":"passed","duration":28000000}}]}]},{"description":"","id":"counter","keyword":"Feature","line":2,"name":"Counter","uri":".\\features\\counter_increases_french.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"counter;counter increases when the button is pressed","name":"Counter increases when the button is pressed","description":"","line":5,"steps":[{"keyword":"Etant ","name":"donné que I pick the colour red","line":6,"match":{"location":".\\features\\counter_increases_french.feature:6"},"result":{"status":"passed","duration":0}},{"keyword":"Et ","name":"I expect the \"counter\" to be \"0\"","line":7,"match":{"location":".\\features\\counter_increases_french.feature:7"},"result":{"status":"passed","duration":45000000}},{"keyword":"Quand ","name":"I tap the \"increment\" button 10 times","line":8,"match":{"location":".\\features\\counter_increases_french.feature:8"},"result":{"status":"passed","duration":2537000000}},{"keyword":"Alors ","name":"I expect the \"counter\" to be \"10\"","line":9,"match":{"location":".\\features\\counter_increases_french.feature:9"},"result":{"status":"passed","duration":30000000}}]}]},{"description":"","id":"drawer","keyword":"Feature","line":1,"name":"Drawer","uri":".\\features\\drawer.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"drawer;should open the drawer","name":"should open the drawer","description":"","line":3,"steps":[{"keyword":"Given ","name":"I open the drawer","line":4,"match":{"location":".\\features\\drawer.feature:4"},"result":{"status":"passed","duration":1477000000}},{"keyword":"Given ","name":"I close the drawer","line":5,"match":{"location":".\\features\\drawer.feature:5"},"result":{"status":"passed","duration":441000000}}]}]},{"description":"","id":"interaction","keyword":"Feature","line":1,"name":"Interaction","uri":".\\features\\long_press_widget.feature","elements":[{"keyword":"Scenario","type":"scenario","id":"interaction;widget can be long pressed","name":"Widget can be long pressed","description":"","line":3,"steps":[{"keyword":"Given ","name":"I expect the \"longPressText\" to be \"Text that has not been long pressed\"","line":4,"match":{"location":".\\features\\long_press_widget.feature:4"},"result":{"status":"passed","duration":41000000}},{"keyword":"When ","name":"I long press the \"longPressText\" text","line":5,"match":{"location":".\\features\\long_press_widget.feature:5"},"result":{"status":"passed","duration":683000000}},{"keyword":"Then ","name":"I expect the \"longPressText\" to be \"Text has been long pressed!\"","line":6,"match":{"location":".\\features\\long_press_widget.feature:6"},"result":{"status":"passed","duration":44000000}}]}]}] \ No newline at end of file diff --git a/lib/src/flutter/flutter_run_process_handler.dart b/lib/src/flutter/flutter_run_process_handler.dart index 8f2dae5..1fc2faa 100644 --- a/lib/src/flutter/flutter_run_process_handler.dart +++ b/lib/src/flutter/flutter_run_process_handler.dart @@ -47,6 +47,7 @@ class FlutterRunProcessHandler extends ProcessHandler { bool _buildApp = true; bool _logFlutterProcessOutput = false; bool _verboseFlutterLogs = false; + bool _keepAppRunning = false; BuildMode _buildMode = BuildMode.Debug; String _workingDirectory; String _appTarget; @@ -91,6 +92,10 @@ class FlutterRunProcessHandler extends ProcessHandler { _verboseFlutterLogs = verbose; } + void setKeepAppRunning(bool keepRunning) { + _keepAppRunning = keepRunning; + } + @override Future run() async { final arguments = ['run', '--target=$_appTarget']; @@ -117,6 +122,10 @@ class FlutterRunProcessHandler extends ProcessHandler { arguments.add('--verbose'); } + if (_keepAppRunning) { + arguments.add('--keep-app-running'); + } + if (_logFlutterProcessOutput) { stdout.writeln( 'Invoking from working directory `${_workingDirectory ?? './'}` command: `flutter ${arguments.join(' ')}`', diff --git a/lib/src/flutter/flutter_test_configuration.dart b/lib/src/flutter/flutter_test_configuration.dart index 61c07f2..d5d5c73 100644 --- a/lib/src/flutter/flutter_test_configuration.dart +++ b/lib/src/flutter/flutter_test_configuration.dart @@ -88,6 +88,10 @@ class FlutterTestConfiguration extends TestConfiguration { /// Defaults to empty String targetDeviceId = ''; + /// Will keep the Flutter application running when done testing + /// Defaults to false + bool keepAppRunningAfterTests = false; + /// Logs Flutter process output to stdout /// The Flutter process is use to start and driver the app under test. /// The output may contain build and run information diff --git a/lib/src/flutter/hooks/app_runner_hook.dart b/lib/src/flutter/hooks/app_runner_hook.dart index 771c5d1..5bc0bfd 100644 --- a/lib/src/flutter/hooks/app_runner_hook.dart +++ b/lib/src/flutter/hooks/app_runner_hook.dart @@ -74,6 +74,7 @@ class FlutterAppRunnerHook extends Hook { ..setDriverConnectionDelay(config.flutterDriverReconnectionDelay) ..setWorkingDirectory(config.targetAppWorkingDirectory) ..setBuildRequired(haveRunFirstScenario ? false : config.build) + ..setKeepAppRunning(config.keepAppRunningAfterTests) ..setBuildFlavor(config.buildFlavor) ..setBuildMode(config.buildMode) ..setDeviceTargetId(config.targetDeviceId); diff --git a/pubspec.lock b/pubspec.lock index cbbd747..5685121 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -7,14 +7,14 @@ packages: name: _fe_analyzer_shared url: "https://pub.dartlang.org" source: hosted - version: "7.0.0" + version: "12.0.0" analyzer: dependency: transitive description: name: analyzer url: "https://pub.dartlang.org" source: hosted - version: "0.39.17" + version: "0.40.6" archive: dependency: transitive description: @@ -35,28 +35,28 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.4.2" + version: "2.5.0-nullsafety.1" boolean_selector: dependency: transitive description: name: boolean_selector url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" characters: dependency: transitive description: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.0.0" + version: "1.1.0-nullsafety.3" charcode: dependency: transitive description: name: charcode url: "https://pub.dartlang.org" source: hosted - version: "1.1.3" + version: "1.2.0-nullsafety.1" cli_util: dependency: transitive description: @@ -70,14 +70,14 @@ packages: name: clock url: "https://pub.dartlang.org" source: hosted - version: "1.0.1" + version: "1.1.0-nullsafety.1" collection: dependency: transitive description: name: collection url: "https://pub.dartlang.org" source: hosted - version: "1.14.13" + version: "1.15.0-nullsafety.3" convert: dependency: transitive description: @@ -91,7 +91,7 @@ packages: name: coverage url: "https://pub.dartlang.org" source: hosted - version: "0.14.1" + version: "0.14.2" crypto: dependency: transitive description: @@ -99,27 +99,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.5" - csslib: - dependency: transitive - description: - name: csslib - url: "https://pub.dartlang.org" - source: hosted - version: "0.16.2" fake_async: dependency: transitive description: name: fake_async url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" file: dependency: transitive description: name: file url: "https://pub.dartlang.org" source: hosted - version: "5.2.1" + version: "6.0.0-nullsafety.2" flutter: dependency: "direct main" description: flutter @@ -146,7 +139,7 @@ packages: name: gherkin url: "https://pub.dartlang.org" source: hosted - version: "1.1.8+4" + version: "1.1.9" glob: dependency: "direct main" description: @@ -154,13 +147,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" - html: - dependency: transitive - description: - name: html - url: "https://pub.dartlang.org" - source: hosted - version: "0.14.0+3" http: dependency: transitive description: @@ -182,13 +168,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" - intl: - dependency: transitive - description: - name: intl - url: "https://pub.dartlang.org" - source: hosted - version: "0.16.1" io: dependency: transitive description: @@ -202,14 +181,14 @@ packages: name: js url: "https://pub.dartlang.org" source: hosted - version: "0.6.2" + version: "0.6.3-nullsafety.2" json_rpc_2: dependency: transitive description: name: json_rpc_2 url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "2.2.2" logging: dependency: transitive description: @@ -223,14 +202,14 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.8" + version: "0.12.10-nullsafety.1" meta: dependency: "direct main" description: name: meta url: "https://pub.dartlang.org" source: hosted - version: "1.1.8" + version: "1.3.0-nullsafety.3" mime: dependency: transitive description: @@ -244,7 +223,7 @@ packages: name: node_interop url: "https://pub.dartlang.org" source: hosted - version: "1.1.1" + version: "1.2.1" node_io: dependency: transitive description: @@ -272,35 +251,35 @@ packages: name: path url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.1" pedantic: dependency: "direct dev" description: name: pedantic url: "https://pub.dartlang.org" source: hosted - version: "1.9.0" + version: "1.10.0-nullsafety.2" platform: dependency: transitive description: name: platform url: "https://pub.dartlang.org" source: hosted - version: "2.2.1" + version: "3.0.0-nullsafety.2" pool: dependency: transitive description: name: pool url: "https://pub.dartlang.org" source: hosted - version: "1.4.0" + version: "1.5.0-nullsafety.2" process: dependency: transitive description: name: process url: "https://pub.dartlang.org" source: hosted - version: "3.0.13" + version: "4.0.0-nullsafety.2" pub_semver: dependency: transitive description: @@ -347,42 +326,42 @@ packages: name: source_map_stack_trace url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.3" source_maps: dependency: transitive description: name: source_maps url: "https://pub.dartlang.org" source: hosted - version: "0.10.9" + version: "0.10.10-nullsafety.2" source_span: dependency: transitive description: name: source_span url: "https://pub.dartlang.org" source: hosted - version: "1.7.0" + version: "1.8.0-nullsafety.2" stack_trace: dependency: transitive description: name: stack_trace url: "https://pub.dartlang.org" source: hosted - version: "1.9.5" + version: "1.10.0-nullsafety.1" stream_channel: dependency: transitive description: name: stream_channel url: "https://pub.dartlang.org" source: hosted - version: "2.0.0" + version: "2.1.0-nullsafety.1" string_scanner: dependency: transitive description: name: string_scanner url: "https://pub.dartlang.org" source: hosted - version: "1.0.5" + version: "1.1.0-nullsafety.1" sync_http: dependency: transitive description: @@ -396,49 +375,49 @@ packages: name: term_glyph url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0-nullsafety.1" test: dependency: "direct dev" description: name: test url: "https://pub.dartlang.org" source: hosted - version: "1.15.2" + version: "1.16.0-nullsafety.5" test_api: dependency: transitive description: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.2.17" + version: "0.2.19-nullsafety.2" test_core: dependency: transitive description: name: test_core url: "https://pub.dartlang.org" source: hosted - version: "0.3.10" + version: "0.3.12-nullsafety.5" typed_data: dependency: transitive description: name: typed_data url: "https://pub.dartlang.org" source: hosted - version: "1.2.0" + version: "1.3.0-nullsafety.3" vector_math: dependency: transitive description: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.0.8" + version: "2.1.0-nullsafety.3" vm_service: dependency: transitive description: name: vm_service url: "https://pub.dartlang.org" source: hosted - version: "4.2.0" + version: "5.5.0" vm_service_client: dependency: transitive description: @@ -473,7 +452,7 @@ packages: name: webkit_inspection_protocol url: "https://pub.dartlang.org" source: hosted - version: "0.7.3" + version: "0.7.4" yaml: dependency: transitive description: @@ -482,5 +461,5 @@ packages: source: hosted version: "2.2.1" sdks: - dart: ">=2.9.0-14.0.dev <3.0.0" + dart: ">=2.10.0-110 <2.11.0" flutter: ">=1.13.0" diff --git a/pubspec.yaml b/pubspec.yaml index bcdd250..e2340cf 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_gherkin description: A Gherkin / Cucumber parser and test runner for Dart and Flutter -version: 1.1.8+9 +version: 1.1.9 homepage: https://github.com/jonsamwell/flutter_gherkin environment: @@ -16,7 +16,7 @@ dependencies: sdk: flutter glob: ^1.1.7 meta: ">=1.1.6 <2.0.0" - gherkin: ^1.1.8+4 + gherkin: ^1.1.9 # gherkin: # path: ../dart_gherkin