Flutter入门项目

coverage report
style: very good analysis
License: MIT

Nero Lab CLI 生成?

Nero Lab CLI 创建的 Nero Lab 项目。


开始上手?

此项目包含 3 种风味

  • 开发
  • 测试
  • 生产

要运行所需的风味,可以使用 VSCode/Android Studio 中的启动配置,或使用以下命令

# Development
$ flutter run --flavor development --target lib/main_development.dart

# Staging
$ flutter run --flavor staging --target lib/main_staging.dart

# Production
$ flutter run --flavor production --target lib/main_production.dart

在将本地分支推送到远程分支之前,请务必执行以下步骤

$ flutter format lib test
$ flutter analyze lib test

*Flutter入门项目可在 iOS、Android 和 Web 上运行。


设置 GitLab?

Git 分支

  1. master 作为开发分支(受保护)
  2. staging(受保护):供 QA 测试应用
  3. production(受保护):用于生产,部署到 Play Store 或 App Store
  4. 功能分支

GitLab Flow

原则

  • 为任务创建一个新的本地分支,并定期将同名分支推送到服务器

  • 任务完成后,请求一个合并请求到 master 分支

  • 当提交的更改经过审查/批准后,将其与 master 分支合并

  • 一旦进入 master 分支,代码必须被集成到公司的内部环境分支,直到达到 production 分支。

  • 合并到 master 分支时,删除开发任务的分支,使仓库更加整洁。

    https://github.com/jadsonjs/gitlab-flow/raw/master/images/flow14.png

功能分支 > Master > Staging > Production

阅读此文以获取更多信息 GitHub – jadsonjs/gitlab-flow: Shows the Gitlab flow workflow

CI 变量

在您的项目中,打开设置 > CI/CD > Variables,并设置此变量

Gitlab CI Variables

  • 编码 Keystore:base64 key.jks
  • 复制 base64 输出,创建一个名为STORE_FILE的变量
  • 将 store 密码保存为STORE_PASSWORD变量
  • 将 key 密码保存为KEY_PASSWORD变量
  • 将 key 别名保存为KEY_ALIAS变量

要通过 Fastlane 进行部署,您需要获取 Google Play Console 的 API 访问权限。要获取 api key json 文件,请遵循 Fastlane 指南的“收集您的 Google 凭据”部分中的步骤。

  • 将 key.json 文件的内容保存为JSON_KEY_DATA变量。

要通过 Fastlane 部署到 Firebase App Distribution,请遵循Firebase App Distribution的步骤。

  • 将 Firebase app id 保存为FIREBASE_APP_ID变量
  • 将 Firebase cli token 保存为FIREBASE_CLI_TOKEN变量,要获取 Firebase cli token,请遵循这些步骤

GitLab CI/CD

这是此项目的 GitLab 流水线可视化
Gitlab Pipeline

阶段

共有 4 个阶段

  1. 测试
  2. 构建
  3. Staging
  4. Internal_test
  5. Production
1. 测试

测试阶段将在所有分支上运行,并执行以下脚本

- flutter format --set-exit-if-changed lib test
- flutter analyze lib test
- flutter test --coverage
- lcov --remove coverage/lcov.info 'lib/*/*.g.dart' 'lib/core/**' -o coverage/lcov.info
- genhtml coverage/lcov.info --output=coverage

如果运行flutter format --set-exit-if-changed lib test后没有文件更改,或者 GitLab CI 会返回失败,请确保此项目中没有错误警告。因此,在将项目推送到远程之前,您需要在本地分支上运行此命令

$ flutter format lib test
$ flutter analyze lib test
2. 构建

构建阶段有两个作业:build_android_staging将在master合并到staging分支时运行,build_android_production将在合并到production分支时运行。

3. Staging

Staging 阶段仅在staging分支上运行,并将应用分发到Firebase App Distribution供 QA 在 staging 风味中进行测试。在Firebase App Distribution中,创建一个名为 Tester 的组,并添加测试者的电子邮件。

4. Internal Test

Internal Test 阶段会将 production 应用分发到 Playstore 的内部测试

5. Production

Production 阶段会将内部测试的应用提升到生产。在Gitlab CI/CD中,内部测试通过后,您需要手动运行此操作。


运行测试?

要运行所有单元和 widget 测试,请使用以下命令

$ flutter test --coverage

要查看生成的覆盖率报告,您可以使用 lcov

# Remove core file and generated file to get actual coverage
$ lcov --remove coverage/lcov.info 'lib/*/*.g.dart' 'lib/core/**' -o coverage/lcov.info

# Generate Coverage Report
$ genhtml coverage/lcov.info -o coverage/

# Open Coverage Report
$ open coverage/index.html

集成测试?

Firebase Test Lab

转到 Firebase Console,如果您还没有项目,请创建一个新项目。然后导航到Quality > Test Lab

https://flutterdart.cn/assets/images/docs/integration-test/test-lab-1.png

上传 Android APK

使用 Gradle 创建 APK

$ pushd android
# flutter build generates files in android/ for building the app
$ flutter build apk --flavor staging -t lib/main_staging.dart
$ ./gradlew app:assembleAndroidTest
$ ./gradlew app:assembleDebug -Ptarget=integration_test/<name>_test.dart
$ popd

其中<name>_test.dart是“项目设置”部分创建的文件。

将“debug”APK 从<flutter_project_directory>/build/app/outputs/apk/debug拖到网页上的Android Robo Test目标。这将启动 Robo 测试并允许您运行其他测试。

https://flutterdart.cn/assets/images/docs/integration-test/test-lab-2.png

点击Run a test,选择Instrumentation测试类型,然后拖动以下两个文件

  • <flutter_project_directory>/build/app/outputs/apk/debug/<file>.apk
  • <flutter_project_directory>/build/app/outputs/apk/androidTest/debug/<file>.apk

https://flutterdart.cn/assets/images/docs/integration-test/test-lab-3.png

如果发生失败,您可以选择红色图标来查看输出

https://flutterdart.cn/assets/images/docs/integration-test/test-lab-4.png

有关更多信息,请阅读 Flutter Integration Firebase Test Lab 或 Flutter 文档 Integration Testing

Flutter 集成测试在 Firebase Test Lab 上

集成测试

真实设备上的集成测试

flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart

QA 测试 Staging 应用

我们将使用 Firebase App Distribution 将 staging 应用分发给测试人员。
要添加测试人员,请在firebase_app_distribution/testers.txt文件夹中添加电子邮件,或在firebase_app_distribution/groups.txt文件夹中添加组,通过逗号分隔电子邮件或组。

示例添加测试人员

示例添加组

Testers, QA

组测试人员需要在Firebase Console中进行设置,转到App Distribution > Testers & Groups,并将测试人员添加到组。


处理翻译?

此项目依赖于 flutter_sheet_localization,并阅读了 flutter_sheet_localization_generator 的文档。以获取更多信息。

用法

1. 创建一个 Google 表格

创建一个包含翻译的表格(遵循以下格式,此处提供了一个示例表格

example

确保您的表格已共享

share

从链接中提取 DOCIDSHEETID 值:https://docs.google.com/spreadsheets/d/<DOCID>/edit#gid=<SHEETID>)

2. 声明一个本地化委托

lib/l10n/localization.dart文件中声明以下AppLocalizationsDelegate类,并使用指向您的表格的SheetLocalization注解。

import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_sheet_localization/flutter_sheet_localization.dart';

part 'localization.g.dart';

@SheetLocalization("DOCID", "SHEETID", 1) // <- See 1. to get DOCID and SHEETID
// the `1` is the generated version. You must increment it each time you want to regenerate
// a new version of the labels.
class AppLocalizationsDelegate
    extends LocalizationsDelegate<AppLocalizationsData> {
  const AppLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => localizedLabels.containsKey(locale);

  @override
  Future<AppLocalizationsData> load(Locale locale) =>
      SynchronousFuture<AppLocalizationsData>(localizedLabels[locale]!);
  @override
  bool shouldReload(AppLocalizationsDelegate old) => false;
}

3. 生成本地化文件

运行以下命令以生成lib/l10n/localization.g.dart文件。

$ flutter packages pub run build_runner build

4. 显示您的标签

import 'package:flutter_starter_project/core/l10n/localizations.dart';

final labels = context.localizations;

print(labels.dates.month.february);
print(labels.templated.hello(firstName: "World"));
print(labels.templated.contact(Gender.male, lastName: "John"));

生成 Icon Android IOS

为 Android 和 iOS 生成启动图标

$ flutter pub run flutter_launcher_icons:main -f flutter_launcher_icons*

生成 Splashscreen Android IOS

为 Android 和 iOS 生成启动屏幕

$ flutter pub run flutter_native_splash:create

GitHub

查看 Github