ogurets_flutter 1.2.7

  • Readme
  • Changelog
  • Example
  • Installing
  • 64

ogurets_flutter #

ogurets is a Gherkin + Cucumber implementation in Dart, focused on making your life writing tests as easy as possible, with the minimum of boilerplate fuss. ogurets_flutter is a flutter extension to ogurets which adds support for:

  • Running against an existing running application (as long as you know the observatory port)
  • Starting the application for you and controlling it to ensure it is allowed to Restart and set its state back to the beginning without having to quit and rerun the application
  • Terminating the application (or not) on completion
  • Allowing you to set a default for restarts or no-restarts and use Gherkin tags to control behaviour.

Rather than repeat how Ogurets operates, check out its documentation.

installing #

in your dev_dependencies section in your pubspec.yaml include:

ogurets_flutter: ^1.2.5

or whichever is the higher version you see on this page.

using Ogurets Flutter #

When doing Gherkin steps with this plugin, you will generally want to have access to the flutter driver. As per the example, you can just inject this. Your test runner will had these additional features:

void main(args) async {
	var def = OguretsOpts()
    ..feature("test_driver/features")
		..instance(FlutterOgurets())
		//..step(...)
        ..step(FlutterHooks)
        ..step(FlutterOguretsHelperStepdefs) // if you want to use the extended steps
	;

	await def.run();
}

If you are using the IntelliJ Plugin then this file and these additions are created for you automatically (as it detects it is a flutter project).

When you wish access to the driver, just inject it as you would anything else.

e.g.

import 'package:ogurets/ogurets.dart';
import 'package:ogurets_flutter/ogurets_flutter.dart';

class CounterStepdefs {
  final FlutterOgurets _world;

  CounterStepdefs(this._world);

  @Then(r'the counter is {int}')
  void theCounterIs(int counter) async {
    // ...

  }
}

vscode #

If you are using Visual Studio Code, you can debug the tests by adding a section like the following to your launch.json. This is for the example solution in the repository.

{
            //Can't run this with the normal working directory because the Dart plugin helpfully tries to launch Flutter, and we 
            //want to run it as dart. 
            "name": "Debug E2E Tests",
            "request": "launch",
            "type": "dart",
            "program": "ogurets_flutter_test.dart",
            "cwd": "example/test_driver",
            "env": {"OGURETS_FLUTTER_WORKDIR":"..", "OGURETS_FLUTTER_START_TIMEOUT":"120", "OGURETS_ADDITIONAL_ARGUMENTS":""},
          }

The ogurets_flutter_test.dart file would have to be modified to look for features in that directory as well, since the launch configuration changes the cwd so that tests can be debugged. Otherwise, the Dart Code plugin attempts to launch as a Flutter rather than Dart debugger.

    ..feature('test_driver/features/counter.feature')
    ..feature('features')

environment variables #

If you wish to control the flutter run via your own command line build, then the important environment variables are the same as ogurets but with the extension of:

  • OGURETS_FLUTTER_FLAVOUR - this passes "--flavor ${OGURETS_FLUTTER_FLAVOUR}" to flutter run. Note the International English spelling.
  • OGURETS_FLUTTER_DEVICE_ID - this passes "-d ${OGURETS_FLUTTER_DEVICE_ID}" to flutter run letting you specify a device to run on.
  • OGURETS_ADDITIONAL_ARGUMENTS - lets you specify any arguments you wish. Arguments in quotes are broken up correctly.
  • OGURETS_FLUTTER_START_TIMEOUT - lets you override the default 60 second timeout to wait for the application to start.

notes #

ogurets flutter cannot be used from the command line tool flutter driver because the library it needs to know what the observatory port is (which is how Flutter and the Flutter Driver communicate). If you wish to include it in your test runs (say on CodeMagic), just use Dart itself and run your _test.dart runner, it will start your main app and control it.

All of the normal Ogurets extensions work

e.g.

flutter emulators --launch apple_ios_simulator
echo ios emulator launched
echo running e2e tests
export OGURETS_FLUTTER_FLAVOUR=dev2
export CUCUMBER_FOLDER=test_driver/features
echo codemagic build servers are a wee bit slower than my laptop so...
export OGURETS_FLUTTER_START_TIMEOUT=480
dart --enable-asserts --enable-vm-service:59546 test_driver/runner_test.dart

If you wish to use the flutter driver command line tool, use ogurets directly and just enable the driver in an instance of your own to make it available to your steps.

screenshots #

ogurets_flutter can take screenshots for you if you are having difficulty in specific environments or if you just wish to capture specific screenshots at a particular scale.

For when you want to determine what is going on, particularly in a headless test environment, if you tag your test with @FlutterScreenshot and ensure the environment variable SCREENSHOT_DIR has been set, then we will take screenshots before every step and once the scenario ends. All screenshots are time stamped and put in the directory you have specified with the SCREENSHOT_DIR variable. Any missing directories in this list will be created as part of the test.

If you wish to capture screenshots with a specific name, then there is a step for this - and it's intended use is to capture screenshots for "whats new" screens or for when you are uploading your application to the stores. For this there are 3 available steps to control this:

  • I take a screenshot called {string}
  • I set the maximum screenshot height to {int}
  • I set the maximum screenshot width to {int}

Furthermore, if you have an extra environment variable called SCREENSHOT_PLATFORM you can easily change the platform between each run of your Cucumber tests and capture different platforms (such as the four recommended for iOS).

debugging #

If you wish to run and debug your Flutter app as a separate process from your Ogurets run, you need to follow the below steps:

  • create a new run profile that points to your "main" used in your Flutter Driver tests. Then add in the Additional Arguments to this run configuration --observatory-port 8888 (or chose some other port).
  • start the application and look for the line when the build spits out: Observatory URL on this device: http://127.0.0.1/XXXX, e.g. Observatory URL
  • open your test run configuration and you will see a field called Observatory URL - paste this link in there. If this is in place when the IDE runs, it will not attempt to run the Flutter app, simply connect to it. From the command line, this is done using the environment variable VM_SERVICE_URL.

At this point you can now operate in normal Flutter development mode, changing code, adding widget tags, debug points and so forth, and re-running your tests again and again as necessary.

authors #

We also thank Jon Samwell of Flutter Gherkin for his idea (and core code) for managing the run of the the application. It has been heavily modified in this version.

1.2.7 #

  • fixes some issues introduced from the previous build

1.2.6 #

  • updated method of adding in flutter extra run parameters as the command line library was chopping them off (tobindh@github.com)

1.2.5 #

  • documentation

1.2.4 #

  • last minute discovery that flutter driver sdk depends on lower version of image lib

1.2.3 #

  • Support for screen snapshotting
  • doesn't reset the app on first run

1.2.2 #

More robust detection of failures. Added OGURETS_FLUTTER_START_TIMEOUT.

1.2.1 #

Added in support for additional parameters for flutter build runs (flavours, device ids and generic additional parameters).

1.1.2 #

Added in override support for which file to actually run

1.1.1 #

This is the first release of ogurets_flutter. As per documentation.

example/lib/main.dart

import 'package:flutter/material.dart';

import 'widget_keys.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Invoke "debug painting" (press "p" in the console, choose the
          // "Toggle Debug Paint" action from the Flutter Inspector in Android
          // Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
          // to see the wireframe for each widget.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              key: Key(WidgetKeys.valueKey),
              style: Theme.of(context).textTheme.display1,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        key: Key(WidgetKeys.addButtonKey),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  ogurets_flutter: ^1.2.7

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:ogurets_flutter/ogurets_flutter.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
40
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
70
Overall:
Weighted score of the above. [more]
64
Learn more about scoring.

We analyzed this package on Mar 31, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.6
  • Flutter: 1.12.13+hotfix.8

Health suggestions

Format lib/flutter_autorun.dart.

Run flutter format to format lib/flutter_autorun.dart.

Maintenance issues and suggestions

No valid SDK. (-20 points)

The analysis could not detect a valid SDK that can use this package.

The description is too long. (-10 points)

Search engines display only the first part of the description. Try to keep the value of the description field in your package's pubspec.yaml file between 60 and 180 characters.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.2.0 <3.0.0
commandline_splitter ^1.5.2 1.5.2
flutter 0.0.0
flutter_driver 0.0.0
image ^2.1.4 2.1.4 2.1.12
logging ^0.11.3+2 0.11.4
ogurets ^3.1.6 3.1.9
Transitive dependencies
ansicolor 1.0.2
archive 2.0.11 2.0.13
args 1.5.2 1.6.0
async 2.4.0 2.4.1
boolean_selector 1.0.5 2.0.0
charcode 1.1.2 1.1.3
collection 1.14.11 1.14.12
convert 2.1.1
crypto 2.1.3 2.1.4
file 5.1.0
flutter_test 0.0.0
fuchsia_remote_debug_protocol 0.0.0
intl 0.16.0 0.16.1
json_rpc_2 2.1.0
matcher 0.12.6
meta 1.1.8
path 1.6.4
petitparser 2.4.0 3.0.2
platform 2.2.1
process 3.0.12
pub_semver 1.4.2 1.4.4
quiver 2.0.5 2.1.3
sky_engine 0.0.99
source_span 1.5.5 1.7.0
sprintf 4.0.2
stack_trace 1.9.3
stream_channel 2.0.0
string_scanner 1.0.5
term_glyph 1.1.0
test_api 0.2.11 0.2.15
typed_data 1.1.6
vector_math 2.0.8
vm_service_client 0.2.6+2 0.2.6+3
web_socket_channel 1.1.0
xml 3.5.0 4.1.0
Dev dependencies
pedantic any 1.8.0+1 1.9.0