Skip to content

Commit

Permalink
Merge pull request #8 from Tune-Fun/feat/auth-test
Browse files Browse the repository at this point in the history
Feature - Unit test
  • Loading branch information
seilylook authored Mar 25, 2024
2 parents b4f0c9c + 087b09a commit 868f6ee
Show file tree
Hide file tree
Showing 26 changed files with 1,405 additions and 43 deletions.
128 changes: 128 additions & 0 deletions .github/workflows/android-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
name: Run Flutter E2E (android) test
on:
push:
branches:
- develop
pull_request:
branches:
- develop

jobs:
e2e:
runs-on: ubuntu-latest
outputs:
SLACK_MESSAGE_TITLE: Flutter E2E Test on ${{ matrix.os }} ${{ matrix.os_version }}
TESTS_EXIT_CODE: ${{ steps.tests_step.outputs.TESTS_EXIT_CODE }}
URL_TO_DETAILS: ${{ steps.tests_step.outputs.URL_TO_DETAILS }}

strategy: # 테스트를 하고자 하는 디바이스 설정
matrix:
os: ["Android API"]
include:
- device_model: "oriole"
os_version: "33"

steps:
# 1. 코드 체크아웃
- name: Github Checkout
uses: actions/checkout@v3

# 2.1 Flutter 설치
- uses: subosito/flutter-action@v2
with:
channel: "stable"

# 2.2. 의존성 설치
- name: Install dependencies
run: flutter pub get

# 2.3. Gradle wrapper 생성
- name: Generate Gradle wrapper
run: flutter build apk --config-only

# 3.1. Patrol CLI 설치
- name: Set up Patrol CLI
run: dart pub global activate patrol_cli

# 3.2. Patrol 빌드
- name: patrol build android
run: patrol build android

# 4.1. service-account.json 인증
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: "${{secrets.GCP_STAGE_SERVICE_ACCOUNT_JSON}}"

# 4.2. gcloud 설정
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v1

# 4.3 ENV 설정
- name: Create .env File
uses: iamsauravsharma/create-dotenv@v1.2.2
with:
env-prefix: "envkey_"
file-name: ".env"
directory: "/home/runner/work/tunefun_front/assets/config/"
env:
IS_SERVER: true
PUBLIC_BASE_URL: ${{secrets.PUBLIC_BASE_URL}}
PUBLIC_USER_REGISTER_URL: ${{secrets.PUBLIC_USER_REGISTER_URL}}
PUBLIC_USER_LOGIN_URL: ${{secrets.PUBLIC_USER_LOGIN_URL}}
PUBLIC_USER_LOGOUT_URL: ${{secrets.PUBLIC_USER_LOGOUT_URL}}
PUBLIC_USER_FIND_USERNAME: ${{secrets.PUBLIC_USER_FIND_USERNAME}}
PUBLIC_USER_ACCESS_TOKEN: ${{secrets.PUBLIC_USER_ACCESS_TOKEN}}
PUBLIC_USER_SET_NEW_PASSWORD: ${{secrets.PUBLIC_USER_SET_NEW_PASSWORD}}
PUBLIC_USER_UPDATE_NICKNAME: ${{secrets.PUBLIC_USER_UPDATE_NICKNAME}}
PUBLIC_USER_FORGOT_PASSWORD_SEND_OTP: ${{secrets.PUBLIC_USER_FORGOT_PASSWORD_SEND_OTP}}
PUBLIC_USER_OTP_RESEND: ${{secrets.PUBLIC_USER_OTP_RESEND}}
PUBLIC_USER_OTP_VERIFY: ${{secrets.PUBLIC_USER_OTP_VERIFY}}
PUBLIC_USER_CHECK_EMAIL_DUPLICATE: ${{secrets.PUBLIC_USER_CHECK_EMAIL_DUPLICATE}}
PUBLIC_USER_CHECK_EMAIL_VERIFIED: ${{secrets.PUBLIC_USER_CHECK_EMAIL_VERIFIED}}
PUBLIC_USER_CHECK_USERNAME_DUPLICATE: ${{secrets.PUBLIC_USER_CHECK_USERNAME_DUPLICATE}}

# 5. Firebase Test Lab 에 APK 업로드 및 테스트 실행
- name: Upload APKs to Firebase Test Lab and wait for tests to finish
id: tests_step
env:
ANDROID_DEVICE_MODEL: ${{ matrix.device_model }}
ANDROID_DEVICE_VERSION: ${{ matrix.os_version }}
run: |
set +e
set -euo pipefail
# Firebase Test Lab 실행 및 결과 저장
output=$(set -euo pipefail && \
gcloud firebase test android run \
--type instrumentation \
--app build/app/outputs/apk/debug/app-debug.apk \
--test build/app/outputs/apk/androidTest/debug/ap-debug-androidTest.apk \
--device model="$ANDROID_DEVICE_MODEL",version="$ANDROID_DEVICE_VERSION",locale=en,orientation=portrait \
--timeout 10m \
--results-bucket="tunefun-6edf5.appspot.com" \
--use-orchestrator \
--environment-variables clearPackageData=true 2>&1)
TESTS_EXIT_CODE=$?
set -e
# Extract the last link using grep, tail, and sed, and write it to Github Summary
link="$(echo "$output" | grep -o 'https://[^ ]*' | tail -1 | sed 's/\[//;s/\]//')"
echo "[Test details on Firebase Test Lab]($link) (Firebase members only)" >> "$GITHUB_STEP_SUMMARY"
echo "URL_TO_DETAILS=$link" >> "$GITHUB_OUTPUT"
echo "TESTS_EXIT_CODE=$TESTS_EXIT_CODE" >> "$GITHUB_OUTPUT"
exit $TESTS_EXIT_CODE
# 6. Slack 메시지 전송
# call_send_slack_message:
# name: Notify on Slack
# uses: ./.github/workflows/send_slack_message.yml
# needs: e2e
# if: always()
# with:
# TESTS_EXIT_CODE: ${{ needs.e2e.outputs.TESTS_EXIT_CODE }}
# SLACK_MESSAGE_TITLE: ${{ needs.e2e.outputs.SLACK_MESSAGE_TITLE }}
# URL_TO_DETAILS: ${{ needs.e2e.outputs.URL_TO_DETAILS }}
# secrets: inherit
141 changes: 141 additions & 0 deletions .github/workflows/ios-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
name: Run Flutter E2E (ios) test
on:
push:
branches:
- develop
pull_request:
branches:
- develop
jobs:
e2e:
runs-on: macos-latest
outputs:
SLACK_MESSAGE_TITLE: Flutter E2E Test on ${{ matrix.os }} ${{ matrix.os_version }}
TESTS_EXIT_CODE: ${{ steps.tests_step.outputs.TESTS_EXIT_CODE }}
URL_TO_DETAILS: ${{ steps.tests_step.outputs.URL_TO_DETAILS }}
strategy:
# 테스트를 하고자 하는 디바이스 설정
matrix:
device_model: ["iphone15pro"]
os_version: ["17.2"]
os: [iOS]
steps:
# 1. 코드 체크아웃
- uses: actions/checkout@v3

# 2.1 Flutter 설치
- uses: subosito/flutter-action@v2
with:
channel: "stable"

# 2.2. 의존성 설치
- name: Install dependencies
run: flutter pub get

# 3.1 Ruby 설치 (Fastlane 사용을 위해)
- name: Install Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7.2
bundler-cache: true

# 3.2 bundle 설치 (Fastlane 사용을 위해)
- name: Install bundle
run: |
cd ios
bundle config path vendor/bundle
bundle install --jobs 4 --retry 3
# 4. Fastlane 사용하여 Certificate, Provisioning Profile 설치
# 5. Fastlane 사용하여 Xcode Code Signing 변경
- name: Sign iOS app
uses: maierj/fastlane-action@v3.0.0
with:
lane: code_sign_developemnt
subdirectory: ios

# 6.1 Patrol CLI 설치
- name: Set up Patrol CLI
run: dart pub global activate patrol_cli

# 6.2 Patrol 빌드
- name: patrol build ios
run: patrol build ios

# 7.1 service-account.json 인증
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v1
with:
credentials_json: "${{secrets.GCP_STAGE_SERVICE_ACCOUNT_JSON}}"

# 7.2 gcloud 설정
- name: Set up Cloud SDK
uses: google-github-actions/setup-gcloud@v1

# 7.3 ENV 설정
- name: Create .env File
uses: iamsauravsharma/create-dotenv@v1.2.2
with:
env-prefix: "envkey_"
file-name: ".env"
directory: "/home/runner/work/tunefun_front/assets/config/"
env:
IS_SERVER: true
PUBLIC_BASE_URL: ${{secrets.PUBLIC_BASE_URL}}
PUBLIC_USER_REGISTER_URL: ${{secrets.PUBLIC_USER_REGISTER_URL}}
PUBLIC_USER_LOGIN_URL: ${{secrets.PUBLIC_USER_LOGIN_URL}}
PUBLIC_USER_LOGOUT_URL: ${{secrets.PUBLIC_USER_LOGOUT_URL}}
PUBLIC_USER_FIND_USERNAME: ${{secrets.PUBLIC_USER_FIND_USERNAME}}
PUBLIC_USER_ACCESS_TOKEN: ${{secrets.PUBLIC_USER_ACCESS_TOKEN}}
PUBLIC_USER_SET_NEW_PASSWORD: ${{secrets.PUBLIC_USER_SET_NEW_PASSWORD}}
PUBLIC_USER_UPDATE_NICKNAME: ${{secrets.PUBLIC_USER_UPDATE_NICKNAME}}
PUBLIC_USER_FORGOT_PASSWORD_SEND_OTP: ${{secrets.PUBLIC_USER_FORGOT_PASSWORD_SEND_OTP}}
PUBLIC_USER_OTP_RESEND: ${{secrets.PUBLIC_USER_OTP_RESEND}}
PUBLIC_USER_OTP_VERIFY: ${{secrets.PUBLIC_USER_OTP_VERIFY}}
PUBLIC_USER_CHECK_EMAIL_DUPLICATE: ${{secrets.PUBLIC_USER_CHECK_EMAIL_DUPLICATE}}
PUBLIC_USER_CHECK_EMAIL_VERIFIED: ${{secrets.PUBLIC_USER_CHECK_EMAIL_VERIFIED}}
PUBLIC_USER_CHECK_USERNAME_DUPLICATE: ${{secrets.PUBLIC_USER_CHECK_USERNAME_DUPLICATE}}

# 8. Firebase Test Lab 에 APK 업로드 및 테스트 실행
- name: Upload iOS App to Firebase Test Lab and wait for tests to finish
id: tests_step
env:
IOS_DEVICE_MODEL: ${{ matrix.device_model }}
IOS_DEVICE_VERSION: ${{ matrix.os_version }}
run: |
set +e
# iOS 테스트 준비 및 Firebase Test Lab 실행
output=$(cd build/ios_integ/Build/Products && \
rm -f ios_tests.zip && \
zip -r ios_tests.zip Release-iphoneos/*.app *.xctestrun && \
cd - && \
gcloud firebase test ios run \
--type xctest \
--test "build/ios_integ/Build/Products/ios_tests.zip" \
--device model="$IOS_DEVICE_MODEL",version="$IOS_DEVICE_VERSION",locale=en_US,orientation=portrait \
--timeout 10m \
--results-bucket="tunefun-6edf5.appspot.com" 2>&1)
TESTS_EXIT_CODE=$?
set -e
# 출력 및 링크 추출
echo "$output"
link="$(echo "$output" | grep -o 'https://[^ ]*' | tail -1 | sed 's/\[//;s/\]//')"
echo "[Test details on Firebase Test Lab]($link) (Firebase members only)" >> "$GITHUB_STEP_SUMMARY"
echo "URL_TO_DETAILS=$link" >> "$GITHUB_OUTPUT"
echo "TESTS_EXIT_CODE=$TESTS_EXIT_CODE" >> "$GITHUB_OUTPUT"
exit $TESTS_EXIT_CODE
# 9. Slack 메시지 전송
# call_send_slack_message:
# name: Notify on Slack
# uses: ./.github/workflows/send_slack_message.yml
# needs: e2e
# if: always()
# with:
# TESTS_EXIT_CODE: ${{ needs.e2e.outputs.TESTS_EXIT_CODE }}
# SLACK_MESSAGE_TITLE: ${{ needs.e2e.outputs.SLACK_MESSAGE_TITLE }}
# URL_TO_DETAILS: ${{ needs.e2e.outputs.URL_TO_DETAILS }}
# secrets: inherit
12 changes: 11 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ android {
compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion

testOptions {
execution "ANDROIDX_TEST_ORCHESTRATOR"
}


compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
Expand All @@ -49,6 +54,9 @@ android {
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "pl.leancode.patrol.PatrolJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: "true"

}

buildTypes {
Expand All @@ -64,4 +72,6 @@ flutter {
source '../..'
}

dependencies {}
dependencies {
androidTestUtil "androidx.test:orchestrator:1.4.2"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.example.tunefun_front; // replace "com.example.myapp" with your app's package

import androidx.test.platform.app.InstrumentationRegistry;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import pl.leancode.patrol.PatrolJUnitRunner;

@RunWith(Parameterized.class)
public class MainActivityTest {
@Parameters(name = "{0}")
public static Object[] testCases() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
// replace "MainActivity.class" with "io.flutter.embedding.android.FlutterActivity.class"
// if your AndroidManifest is using: android:name="io.flutter.embedding.android.FlutterActivity"
instrumentation.setUp(MainActivity.class);
instrumentation.waitForPatrolAppService();
return instrumentation.listDartTests();
}

public MainActivityTest(String dartTestName) {
this.dartTestName = dartTestName;
}

private final String dartTestName;

@Test
public void runDartTest() {
PatrolJUnitRunner instrumentation = (PatrolJUnitRunner) InstrumentationRegistry.getInstrumentation();
instrumentation.runDartTest(dartTestName);
}
}
29 changes: 29 additions & 0 deletions integration_test/app_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:patrol/patrol.dart';
import 'package:tunefun_front/constants/dummy_data.dart';
import 'package:tunefun_front/features/article/widgets/article_card.dart';
import 'package:tunefun_front/features/article/widgets/article_list.dart';
import 'package:tunefun_front/features/home/views/home_view.dart';
import 'package:tunefun_front/main.dart';
import 'package:patrol_finders/patrol_finders.dart';

void main() {
testWidgets(
'Main Screen test',
(WidgetTester tester) async {
PatrolTester $ = PatrolTester(
tester: tester,
config: const PatrolTesterConfig(),
);
await $.pumpWidget(
const ProviderScope(
child: MyApp(),
),
);
expect($('TuneFun'), findsWidgets);
expect($(const HomeScreen()), findsOneWidget);
expect($(const ArticleList()), findsWidgets);
},
);
}
Loading

0 comments on commit 868f6ee

Please sign in to comment.