Flutter 颤振综合试验的机器人模式

Flutter 颤振综合试验的机器人模式,flutter,integration-testing,Flutter,Integration Testing,为了使颤振集成测试易于阅读,我尝试使用robot模式编写如下代码(链接): 基本robot类如下所示: class RobotBase { RobotBase(this.driver, this.finder); final FlutterDriver driver; final SerializableFinder finder; sees(String valueKey) async { print("sees: $valueKey"); await dr

为了使颤振集成测试易于阅读,我尝试使用robot模式编写如下代码(链接):

基本robot类如下所示:

class RobotBase {
  RobotBase(this.driver, this.finder);

  final FlutterDriver driver;
  final SerializableFinder finder;

  sees(String valueKey) async {
    print("sees: $valueKey");
    await driver.waitFor(find.byValueKey(valueKey));
  }

  seesNot(String valueKey) async {
    print("sees not: $valueKey");
    await driver.waitForAbsent(find.byValueKey(valueKey));
  }
}
class HomeRobot extends Robot {
  HomeRobot(FlutterDriver driver)
      : super(driver, find.byValueKey(home_keys.page));

  Future<HomeRobot> seesFromPlacesField() async {
    await sees(home_keys.fromPlaceField);
    return this;
  }

  Future<HomeRobot> seesToPlacesField() async {
    await sees(home_keys.toPlaceField);
    return this;
  }

  Future<HomeRobot> seesNotSwapButton() async {
    await seesNot(home_keys.swapButton);
    return this;
  }

  Future<HomeRobot> seesSwapButton() async {
    await sees(home_keys.swapButton);
    return this;
  }
}
test('home', () async {
  HomeRobot robot = HomeRobot(driver, Future.value(null));
  await robot
      .seesFromPlacesField()
      .seesToPlacesField()
      .seesNotSwapButton()
      .tapsOnFromPlacesField()
      .seesSearchField()
      .seesBackButton()
      .tapsOnBackButton()
      .seesFromPlacesField()
      .work;
});
还有一个像这样的机器人:

class RobotBase {
  RobotBase(this.driver, this.finder);

  final FlutterDriver driver;
  final SerializableFinder finder;

  sees(String valueKey) async {
    print("sees: $valueKey");
    await driver.waitFor(find.byValueKey(valueKey));
  }

  seesNot(String valueKey) async {
    print("sees not: $valueKey");
    await driver.waitForAbsent(find.byValueKey(valueKey));
  }
}
class HomeRobot extends Robot {
  HomeRobot(FlutterDriver driver)
      : super(driver, find.byValueKey(home_keys.page));

  Future<HomeRobot> seesFromPlacesField() async {
    await sees(home_keys.fromPlaceField);
    return this;
  }

  Future<HomeRobot> seesToPlacesField() async {
    await sees(home_keys.toPlaceField);
    return this;
  }

  Future<HomeRobot> seesNotSwapButton() async {
    await seesNot(home_keys.swapButton);
    return this;
  }

  Future<HomeRobot> seesSwapButton() async {
    await sees(home_keys.swapButton);
    return this;
  }
}
test('home', () async {
  HomeRobot robot = HomeRobot(driver, Future.value(null));
  await robot
      .seesFromPlacesField()
      .seesToPlacesField()
      .seesNotSwapButton()
      .tapsOnFromPlacesField()
      .seesSearchField()
      .seesBackButton()
      .tapsOnBackButton()
      .seesFromPlacesField()
      .work;
});
或者这个(等待):

有没有关于如何把这个很好地链接起来的想法

解决方案

机器人完成“工作”:

class HomeRobot extends Robot {
  HomeRobot(FlutterDriver driver, Future<void> work) : super(driver, work);

  HomeRobot seesFromPlacesField() {
    work = work.then((_) async => await seesKey(keys.homePageFromPlaceField));
    return this;
  }

  SearchRobot tapsOnFromPlacesField() {
    work = work.then((_) async => await tapsOnKey(keys.homePageFromPlaceField));
    return SearchRobot(driver, work);
  }

  // ...
}

class SearchRobot extends Robot {
  SearchRobot(FlutterDriver driver, Future<void> work) : super(driver, work);

  SearchRobot seesBackButton() {
    work = work.then((_) async => await seesTooltip(Robot.backButtonTooltip));
    return this;
  }

  HomeRobot tapsOnBackButton() {
    work = work.then((_) async => await tapsOnTooltip(Robot.backButtonTooltip));
    return HomeRobot(driver, work);
  }

  // ...
}

我试图修改您想要的API,但是为了做到这一点,我添加了第二个类。本例中的机器人包含与驱动程序交互所需的实际异步命令。相应的“Work”类包含一个未来,当您对它调用方法时,它会逐渐建立这个未来。这些方法反过来调用机器人上的实际异步工作,但是我们可以继续调用它们,而不必等待机器人完成。在结束时,我们返回最终的未来,可以等待所有的工作完成

注意,在这种情况下,我们不能使用
语法,因为我们需要对工作类返回的值调用
wait

 final driver = await FlutterDriver.connect();
 final robot = HomeRobot(driver);
 await robot.start()
   .seesFromPlacesField()
   .seesToPlacesField()
   .seesNotSwapButton()
   .work();


class HomeRobot {
  HomeRobot(this.driver);
  final FlutterDriver driver;

  /// Create a new work class which builds up a Future.
  HomeRobotWork start() => new HomeRobotWork(this);

  Future<void> _seesFromPlacesField() async { ... }

  Future<void> _seesToPlacesField() async { ... }

  Future<void> _seesNotSwapButton() async { ... }
}

class HomeRobotWork {
  HomeRobotWork(this.robot);
  final HomeRobot robot;
  Future<void> _result = new Future.value(null);

  /// Add a future onto the result value
  void seesFromPlacesField() {
    _result = _result.then((_) => robot._seesFromPlacesField());
    return this;
  }

  void seesToPlacesField() {
    _result = _result.then((_) => robot._seesToPlacesField());
    return this;
  }

  void seesNotSwapButton() {
    _result = _result.then((_) => robot._seesNotSwapButton());
    return this;
  }

  Future<void> work() => _result;
}
final driver=wait-driver.connect();
最终机器人=家庭机器人(驾驶员);
等待robot.start()
.seesfromsplacesfield()
.请参见StopPlacesfield()
.请参见snotswapbutton()
.工作();
类家庭机器人{
家庭机器人(这个。司机);
最终驾驶员;
///创建一个新的工人阶级,建立未来。
HomeRobotWork start()=>新的HomeRobotWork(此);
Future _seesfromsplacesfield()异步{…}
Future _seeStopPlacesField()异步{…}
未来(见snotswapbutton()异步{…}
}
班级作业机器人{
家庭机器人(this.robot);
家庭机器人;
Future _result=新的Future.value(空);
///将未来添加到结果值上
void seesFromPlacesField(){
_结果=\u结果。然后((\u)=>robot.\u从placesfield()查看);
归还这个;
}
void请参见stoplacesfield(){
_结果=\u结果。然后((\u)=>robot.\u请参见stoplacesfield());
归还这个;
}
void请参见snotswapbutton(){
_结果=_result.然后(()=>机器人._参见snotswapbutton());
归还这个;
}
未来工作()=>\u结果;
}

这种图案在dart中是无用的。您可以直接使用
接线员来连接呼叫。无需返回此值级联运算符在这种情况下不起作用,因为我必须等待每个未来,然后才能继续下一步。此外,未来还可以返回另一个机器人,例如,当HomeRobot点击DetailButton时,将返回一个带有其他可能UI选项的HomeDetailRobot。我的坏消息,算了吧
 final driver = await FlutterDriver.connect();
 final robot = HomeRobot(driver);
 await robot.start()
   .seesFromPlacesField()
   .seesToPlacesField()
   .seesNotSwapButton()
   .work();


class HomeRobot {
  HomeRobot(this.driver);
  final FlutterDriver driver;

  /// Create a new work class which builds up a Future.
  HomeRobotWork start() => new HomeRobotWork(this);

  Future<void> _seesFromPlacesField() async { ... }

  Future<void> _seesToPlacesField() async { ... }

  Future<void> _seesNotSwapButton() async { ... }
}

class HomeRobotWork {
  HomeRobotWork(this.robot);
  final HomeRobot robot;
  Future<void> _result = new Future.value(null);

  /// Add a future onto the result value
  void seesFromPlacesField() {
    _result = _result.then((_) => robot._seesFromPlacesField());
    return this;
  }

  void seesToPlacesField() {
    _result = _result.then((_) => robot._seesToPlacesField());
    return this;
  }

  void seesNotSwapButton() {
    _result = _result.then((_) => robot._seesNotSwapButton());
    return this;
  }

  Future<void> work() => _result;
}