การทดสอบแอปบน Mobile แบบอัตโนมัติมีความซับซ้อนกว่าการทดสอบ Web Application เพราะต้องจัดการทั้ง Simulator, Emulator, Real Device, Native UI, Accessibility, Application State และระบบปฏิบัติการ iOS/Android

Mobilewright เป็น Mobile Automation Framework ที่ได้รับแรงบันดาลใจจาก Playwright โดยนำแนวคิด เช่น

  • getByRole()
  • getByLabel()
  • getByText()
  • getByTestId()
  • expect()
  • Auto-waiting
  • Retry Assertion

มาใช้กับ Native Mobile Application

จึงเหมาะกับทีมที่ใช้ Playwright อยู่แล้วและต้องการนำ Developer Experience แบบเดียวกันมาสู่ Mobile Testing

บทความนี้อ้างอิง Mobilewright Documentation และ GitHub Repository ที่ตรวจสอบ ณ วันที่ 25 กันยายน 2026


#Mobilewright คืออะไร

Mobilewright เป็น Framework สำหรับทำ Mobile App Testing และ Automation ที่รองรับ

  • iOS Simulator
  • Android Emulator
  • iPhone/iPad จริง
  • Android Device จริง
  • Remote Device
  • Cloud Device Provider

รูปแบบ API มีลักษณะคล้าย Playwright

await screen
  .getByLabel('Email')
  .fill('student@example.com');

await screen
  .getByRole('button', { name: 'Sign In' })
  .tap();

await expect(
  screen.getByText('Welcome back')
).toBeVisible();

ถ้าเคยใช้ Playwright จะพบว่าแนวคิดใกล้เคียงกันมาก

await page
  .getByLabel('Email')
  .fill('student@example.com');

await page
  .getByRole('button', { name: 'Sign In' })
  .click();

ความแตกต่างสำคัญคือ Playwright ทำงานกับ Web DOM เป็นหลัก ส่วน Mobilewright ทำงานกับ Native Mobile UI และ Accessibility Tree


#Architecture ของ Mobilewright

flowchart LR
    A[Test Script<br/>TypeScript] --> B[@mobilewright/test]
    B --> C[Mobilewright Core]
    C --> D[Mobile Driver]
    D --> E[iOS Simulator]
    D --> F[iOS Device]
    D --> G[Android Emulator]
    D --> H[Android Device]
    C -. Remote .-> I[Remote / Cloud Driver]
    I --> J[Cloud Devices]

องค์ประกอบสำคัญประกอบด้วย

#screen

ใช้ค้นหาและโต้ตอบกับ UI

screen.getByText('Welcome')
screen.getByLabel('Email')
screen.getByTestId('login-submit')
screen.getByRole('button', { name: 'Login' })

#device

ใช้ควบคุม Device และ Application เช่น

  • Launch App
  • Terminate App
  • Deep Link
  • Geolocation
  • Device-level Operation

#Accessibility Tree

Mobilewright ใช้ข้อมูล Semantic จาก Accessibility Tree เพื่อให้ Locator อ่านง่ายและสามารถใช้ Test Logic เดียวกันข้าม iOS และ Android ได้


#จุดเด่นของ Mobilewright

#1. Playwright-style API

ตัวอย่าง

await screen
  .getByRole('button', { name: 'Login' })
  .tap();

อ่านง่ายกว่าการอ้าง Coordinate หรือ Selector ที่ผูกกับโครงสร้าง UI มากเกินไป


#2. Auto-waiting

Mobilewright มี Auto-waiting ก่อนทำ Action

เช่น

await screen
  .getByRole('button', { name: 'Submit' })
  .tap();

Framework จะรอให้ Element อยู่ในสถานะที่พร้อมสำหรับ Interaction

ดังนั้นควรหลีกเลี่ยง

await new Promise(resolve =>
  setTimeout(resolve, 5000)
);

และใช้ Assertion ที่มี Auto-retry แทน

await expect(
  screen.getByText('Dashboard')
).toBeVisible();

#3. Semantic Locator

Mobilewright รองรับ Locator ที่สื่อความหมาย

screen.getByTestId('login-button')

screen.getByRole(
  'button',
  { name: 'Sign In' }
)

screen.getByLabel('Email')

screen.getByText('Welcome')

แนวทางนี้ช่วยลด Flaky Test ที่เกิดจาก Layout หรือโครงสร้าง UI เปลี่ยน


#4. Retry Assertion

ตัวอย่าง

await expect(
  screen.getByText('Login successful')
).toBeVisible();

Assertion จะตรวจซ้ำจนสำเร็จหรือหมด Timeout


#5. Cross-platform

getByRole() สามารถใช้ Test Logic เดียวกันกับ iOS และ Android ได้ เพราะ Mobilewright ทำการ Normalize Native UI Type ให้เป็น Semantic Role


#Requirement

#Node.js

เอกสารหลักของ Repository ระบุ Node.js ขั้นต่ำ 20.19+ ขณะที่ Windows Setup Guide ระบุ 22.12+

ดังนั้นสำหรับ Project ใหม่ แนะนำ

Node.js 22.12+

หรือใช้ Node.js LTS รุ่นใหม่ที่รองรับ

ตรวจสอบเวอร์ชัน

node --version

#Android

ต้องมีโดยทั่วไป

  • Node.js
  • JDK
  • Android SDK
  • Android Platform Tools
  • ADB
  • Android Emulator หรือ Android Device
  • ANDROID_HOME

Windows รองรับ Android Testing โดยตรง


#iOS

ต้องมี

  • macOS
  • Xcode
  • Xcode Command Line Tools
  • iOS Simulator หรือ iOS Device

เนื่องจาก iOS Simulator ต้องใช้ Xcode จึงไม่สามารถรัน Local iOS Simulator บน Windows ได้


#ตรวจสอบ Environment

ใช้

npx mobilewright doctor

ตรวจเฉพาะ Android

npx mobilewright doctor \
  --category android

ตรวจเฉพาะ iOS

npx mobilewright doctor \
  --category ios

Output แบบ JSON

npx mobilewright doctor \
  --json

คำสั่งนี้ช่วยตรวจสอบ Environment เช่น

  • Node.js
  • Java
  • Android SDK
  • ADB
  • Emulator
  • Xcode
  • Device

#สร้าง Project

ติดตั้ง Mobilewright

npm install mobilewright

หากต้องการใช้ Test Fixtures

npm install \
  --save-dev \
  mobilewright \
  @mobilewright/test

จากนั้นสร้าง Config เริ่มต้น

npx mobilewright init

ตัวอย่างโครงสร้าง

mobilewright-demo/
├── mobilewright.config.ts
├── package.json
└── tests/
    └── login.test.ts

#ตรวจสอบ Device

ใช้คำสั่ง

npx mobilewright devices

ตัวอย่าง

ID          Name            Platform    Type
------------------------------------------------
...         iPhone 17 Pro   ios         simulator
...         Pixel           android     emulator

#Config สำหรับ Android

สร้างไฟล์

mobilewright.config.ts

ตัวอย่าง

import {
  defineConfig
} from 'mobilewright';

export default defineConfig({

  platform: 'android',

  bundleId: 'com.example.myapp',

  deviceName: /Pixel/,

  installApps:
    './builds/app.apk',

  timeout: 30_000,

});

ถ้าติดตั้งแอปไว้แล้ว สามารถใช้เพียง

import {
  defineConfig
} from 'mobilewright';

export default defineConfig({

  platform: 'android',

  bundleId:
    'com.example.myapp',

});

#Config สำหรับ iOS

import {
  defineConfig
} from 'mobilewright';

export default defineConfig({

  platform: 'ios',

  bundleId:
    'com.example.myapp',

  deviceName:
    /iPhone/,

  installApps:
    './builds/MyApp.ipa',

  timeout:
    30_000,

});

#เขียน Test แรก

สร้าง

tests/home.test.ts

จากนั้นเขียน

import {
  test,
  expect
} from '@mobilewright/test';

test(
  'เปิดแอปและแสดง Home Screen',
  async ({ screen }) => {

    await expect(
      screen.getByText('Welcome')
    ).toBeVisible();

  }
);

รัน

npx mobilewright test

#Workshop: ทดสอบ Login

สมมติ Mobile App มีหน้าจอ

Email
Password

[ Sign In ]

และหลัง Login สำเร็จแสดง

Welcome back

สร้างไฟล์

tests/login.test.ts
import {
  test,
  expect
} from '@mobilewright/test';

test(
  'ผู้ใช้สามารถ Login ได้',
  async ({ screen }) => {

    await screen
      .getByLabel('Email')
      .fill(
        'student@example.com'
      );

    await screen
      .getByLabel('Password')
      .fill(
        'secret123'
      );

    await screen
      .getByRole(
        'button',
        {
          name: 'Sign In'
        }
      )
      .tap();

    await expect(
      screen.getByText(
        'Welcome back'
      )
    ).toBeVisible();

  }
);

รันเฉพาะไฟล์

npx mobilewright test \
  tests/login.test.ts

#Negative Test

ควรมีทั้ง Positive และ Negative Scenario

import {
  test,
  expect
} from '@mobilewright/test';

test(
  'Login ไม่สำเร็จเมื่อ Password ไม่ถูกต้อง',
  async ({ screen }) => {

    await screen
      .getByLabel('Email')
      .fill(
        'student@example.com'
      );

    await screen
      .getByLabel('Password')
      .fill(
        'wrong-password'
      );

    await screen
      .getByRole(
        'button',
        {
          name: 'Sign In'
        }
      )
      .tap();

    await expect(
      screen.getByText(
        'Invalid credentials'
      )
    ).toBeVisible();

  }
);

#Locator ที่ควรรู้

#getByTestId()

screen.getByTestId(
  'login-submit'
)

เหมาะสำหรับ Element ที่ทีมพัฒนากำหนด Test ID ไว้ชัดเจน


#getByRole()

screen.getByRole(
  'button',
  {
    name: 'Submit'
  }
)

เหมาะสำหรับ Cross-platform Test


#getByLabel()

screen.getByLabel(
  'Email'
)

เหมาะกับ Input หรือ Element ที่มี Accessibility Label


#getByText()

screen.getByText(
  'Welcome'
)

เหมาะกับข้อความที่แสดงให้ผู้ใช้เห็น


#Locator Priority

Mobilewright Inspector ใช้ลำดับ Locator โดยประมาณ

getByTestId
      ↓
getByRole
      ↓
getByLabel
      ↓
getByText

ใน Project จริงควรเลือก Locator ที่

  • Unique
  • สื่อความหมาย
  • ไม่ผูกกับ Layout
  • ไม่พึ่ง Coordinate
  • ไม่เปลี่ยนง่ายเมื่อ Refactor

#Mobilewright Inspector

เปิดด้วย

npx mobilewright inspect

Inspector เป็น Browser-based UI สำหรับดู

  • Screenshot
  • Element Tree
  • Locator
  • Duplicate Locator
  • Bounding Box

Default Port ปัจจุบันคือ

4621

กำหนด Port เอง

npx mobilewright inspect \
  --port 8080

Inspector เหมาะมากสำหรับค้นหา Locator ก่อนเขียน Test


#Assertion

ตัวอย่างที่ใช้บ่อย

#Visible

await expect(
  screen.getByText('Welcome')
).toBeVisible();

#Hidden

await expect(
  screen.getByText('Loading')
).toBeHidden();

#Enabled

await expect(
  screen.getByRole(
    'button',
    {
      name: 'Submit'
    }
  )
).toBeEnabled();

#Disabled

await expect(
  screen.getByRole(
    'button',
    {
      name: 'Submit'
    }
  )
).toBeDisabled();

Assertion แบบ Locator มี Auto-retry


#Chaining Locator

สามารถจำกัดขอบเขตการค้นหา Element

const row =
  screen
    .getByType('Cell')
    .first();

await row
  .getByRole(
    'button',
    {
      name: 'Delete'
    }
  )
  .tap();

นอกจากนี้ยังมี

screen.getByRole('button').first();

screen.getByRole('button').last();

screen.getByRole('button').nth(2);

นับ Element

const count =
  await screen
    .getByRole('listitem')
    .count();

#ทดสอบ Deep Link

สมมติแอปรองรับ

myapp://profile/123

เขียน Test ได้ในแนวทาง

test(
  'เปิด Profile ผ่าน Deep Link',
  async ({
    device,
    screen
  }) => {

    await device.openUrl(
      'myapp://profile/123'
    );

    await expect(
      screen.getByText(
        'Profile'
      )
    ).toBeVisible();

  }
);

เหมาะสำหรับทดสอบ

  • Product Detail
  • Payment Callback
  • Profile
  • Notification Navigation
  • App Link / Universal Link

#Screenshot

Capture Screenshot

npx mobilewright screenshot

กำหนดชื่อไฟล์

npx mobilewright screenshot \
  -o home.png

เลือก Device

npx mobilewright screenshot \
  -d <device-id>

#HTML Report

รันพร้อม HTML Reporter

npx mobilewright test \
  --reporter html

เปิด Report

npx mobilewright show-report

โดย Default Report Server ใช้

localhost:9323

HTML Report ช่วยตรวจสอบ

  • Passed
  • Failed
  • Error
  • Screenshot
  • Attachment
  • Test Result

#Filter Test

รันเฉพาะ Test ที่ชื่อ Match

npx mobilewright test \
  --grep "login"

ข้าม Test ที่ Match

npx mobilewright test \
  --grep-invert "flaky"

ดูรายการ Test โดยไม่รัน

npx mobilewright test \
  --list

#Retry

ใช้ CLI

npx mobilewright test \
  --retries 2

อย่างไรก็ตาม Retry ไม่ควรใช้เพื่อซ่อนปัญหา Flaky Test

ควรวิเคราะห์สาเหตุ เช่น

  • Locator ไม่ Stable
  • Data ชนกัน
  • Network ไม่ Deterministic
  • App State ไม่ Reset
  • Animation
  • Device Resource ไม่เพียงพอ

#Parallel Testing

รันหลาย Worker

npx mobilewright test \
  --workers 4

ใน Mobile Testing จำนวน Worker มักสัมพันธ์กับจำนวน Device ที่ใช้ได้

Worker 1 → Device 1
Worker 2 → Device 2
Worker 3 → Device 3
Worker 4 → Device 4

ดังนั้นการเพิ่ม Worker โดยไม่มี Device เพียงพอไม่ได้ทำให้ Test เร็วขึ้นโดยอัตโนมัติ


#iOS และ Android ใน Test Suite เดียว

สามารถกำหนด Projects

import {
  defineConfig
} from 'mobilewright';

export default defineConfig({

  testDir: './tests',

  bundleId:
    'com.example.myapp',

  projects: [

    {
      name: 'ios',

      use: {
        platform: 'ios',

        installApps:
          './builds/MyApp.ipa',
      },
    },

    {
      name: 'android',

      use: {
        platform: 'android',

        installApps:
          './builds/app.apk',
      },
    },

  ],

});

รัน Android

npx mobilewright test \
  --project android

รัน iOS

npx mobilewright test \
  --project ios

#โครงสร้าง Project ที่แนะนำ

mobile-tests/
├── mobilewright.config.ts
├── package.json
├── tests/
│   ├── auth/
│   │   ├── login.test.ts
│   │   └── logout.test.ts
│   ├── profile/
│   │   └── profile.test.ts
│   └── checkout/
│       └── checkout.test.ts
├── fixtures/
│   └── test-data.ts
└── builds/
    ├── app.apk
    └── MyApp.ipa

แนะนำให้จัด Test ตาม

Feature
หรือ
User Journey

เช่น

auth/
checkout/
orders/
profile/
payment/

#CI/CD Workflow

แนวคิด Pipeline

flowchart LR
    A[Push / Pull Request]
      --> B[Build Mobile App]

    B --> C[Prepare Device]

    C --> D[Install App]

    D --> E[Mobilewright Test]

    E --> F[HTML Report]

    F --> G[Upload Artifact]

#ตัวอย่าง GitHub Actions

ตัวอย่าง Conceptual Workflow

name: Mobile Test

on:
  push:
    branches:
      - main

  pull_request:

jobs:

  mobile-test:

    runs-on: macos-latest

    steps:

      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 22

      - name: Install Dependencies
        run: npm ci

      - name: Check Environment
        run: npx mobilewright doctor

      - name: Run Tests
        run: |
          npx mobilewright test \
            --reporter html

      - name: Upload Report
        if: ${{ !cancelled() }}
        uses: actions/upload-artifact@v4
        with:
          name: mobilewright-report
          path: mobilewright-report/

การใช้งานจริงต้องเตรียม Simulator/Emulator หรือ Remote Device ให้พร้อมตาม Platform ที่ทดสอบ


#Mobilewright กับ Accessibility Tree

แนวคิดสำคัญของ Mobilewright คือ

Mobile UI
   ↓
Accessibility Tree
   ↓
Semantic Element
   ↓
Locator
   ↓
Action / Assertion

ตัวอย่าง

screen.getByRole(
  'button',
  {
    name: 'Sign In'
  }
)

ข้อดีคือ

  1. Test อ่านง่าย
  2. Cross-platform ได้ง่ายขึ้น
  3. ลดการใช้ Coordinate
  4. ช่วยส่งเสริม Accessibility ที่ดี
  5. เหมาะกับ AI Agent ที่ต้องอ่าน UI ในรูปแบบ Semantic

#Mobilewright vs Playwright

ประเด็น Playwright Mobilewright
เป้าหมาย Web App Native Mobile App
UI Model DOM Native UI / Accessibility Tree
Object page screen, device
Interaction click() tap()
Browser Chromium, Firefox, WebKit ไม่ใช่ Browser Automation เป็นหลัก
iOS/Android Native ไม่ใช่เป้าหมายหลัก รองรับ
Auto-wait มี มี
Semantic Locator มี มี

Mobilewright ไม่ได้มาแทน Playwright สำหรับ Web แต่เป็นการนำแนวคิดแบบ Playwright มาใช้กับ Mobile Native Testing


#Mobilewright vs Appium

ประเด็น Mobilewright Appium
API Style Playwright-style WebDriver-style
Auto-wait Built-in ขึ้นกับการออกแบบ Test
Locator Semantic-focused หลาย Strategy
Setup เน้นง่าย มี Server/Driver Ecosystem
Cross-platform iOS + Android iOS + Android
Ecosystem ใหม่กว่า Mature กว่า
Accessibility Tree เน้น รองรับผ่าน Platform Driver

Appium มี Ecosystem ที่ใหญ่และ Mature กว่า ขณะที่ Mobilewright เหมาะกับทีมที่ต้องการ Developer Experience ใกล้ Playwright


#Test Pyramid สำหรับ Mobile App

Mobile E2E Test ไม่ควรใช้แทน Testing ทุกระดับ

flowchart TB
    A[Mobile E2E<br/>Mobilewright]
    B[Integration / API Test]
    C[Unit Test]

    A --> B
    B --> C

#Unit Test

ใช้ทดสอบ

  • Business Logic
  • Validation
  • State
  • Utility Function

#Integration/API Test

ใช้ทดสอบ

  • Backend API
  • Service
  • Database
  • Integration

#Mobile E2E Test

ใช้ทดสอบ User Journey สำคัญ

  • Login
  • Register
  • Checkout
  • Payment
  • Profile
  • Deep Link
  • Critical Navigation

#Best Practices

#1. ใช้ Semantic Locator

แนะนำ

getByTestId()
getByRole()
getByLabel()
getByText()

หลีกเลี่ยง Fixed Coordinate หากไม่จำเป็น


#2. อย่าใช้ Sleep โดยไม่มีเหตุผล

ไม่ควร

await sleep(5000);

ควร

await expect(
  screen.getByText(
    'Dashboard'
  )
).toBeVisible();

#3. ให้แต่ละ Test Independent

หลีกเลี่ยงการออกแบบแบบ

Test A Login
   ↓
Test B Edit Profile
   ↓
Test C Logout

ที่ Test B และ C ต้องพึ่งผลจาก Test ก่อนหน้า

แต่ละ Test ควร Setup State ของตัวเองเท่าที่ทำได้


#4. ใช้ Test Account

อย่า Hard-code Credential จริงลง Repository

ใช้ Environment Variable

const email =
  process.env.TEST_USER!;

const password =
  process.env.TEST_PASSWORD!;

ใน CI ควรเก็บค่าผ่าน Secret Management


#5. กำหนด Test ID ตั้งแต่ Development

ตัวอย่าง

login-email
login-password
login-submit
checkout-pay
profile-save

ช่วยให้ Automation Test Stable ขึ้น


#6. เก็บ Artifact เมื่อ Test Fail

ควรเก็บ

  • Screenshot
  • HTML Report
  • App Log
  • Device Log
  • UI/Accessibility Information

เพื่อช่วยวิเคราะห์ Root Cause


#Workflow ที่แนะนำ

flowchart LR
    A[Developer]
      --> B[Unit Test]

    B --> C[API / Integration]

    C --> D[Mobilewright Smoke Test]

    D --> E[Pull Request]

    E --> F[CI Regression]

    F --> G[Real / Cloud Devices]

    G --> H[Release]

สำหรับ Pull Request อาจรันเฉพาะ Smoke Test

Launch App
Login
Main Navigation
Critical Feature

ส่วนก่อน Release จึงค่อยรัน Full Regression หลาย Device และ OS Version


#คำสั่ง Mobilewright ที่ควรรู้

# install
npm install mobilewright

# initialize
npx mobilewright init

# check environment
npx mobilewright doctor

# Android doctor
npx mobilewright doctor \
  --category android

# devices
npx mobilewright devices

# inspector
npx mobilewright inspect

# run all tests
npx mobilewright test

# run file
npx mobilewright test \
  tests/login.test.ts

# filter
npx mobilewright test \
  --grep "login"

# retries
npx mobilewright test \
  --retries 2

# workers
npx mobilewright test \
  --workers 4

# project
npx mobilewright test \
  --project android

# HTML report
npx mobilewright test \
  --reporter html

# open report
npx mobilewright show-report

# screenshot
npx mobilewright screenshot \
  -o home.png

#Checklist สำหรับ Workshop

[ ] Node.js 22.12+
[ ] Mobilewright
[ ] @mobilewright/test
[ ] Android SDK / Xcode
[ ] Emulator / Simulator
[ ] Application Build
[ ] Bundle ID
[ ] Accessibility Label
[ ] Test ID

จากนั้น

npx mobilewright doctor
npx mobilewright devices
npx mobilewright inspect
npx mobilewright test

#สรุป

Mobilewright เป็น Framework สำหรับ Mobile Test Automation ที่น่าสนใจ โดยเฉพาะทีมที่คุ้นเคยกับ Playwright และ TypeScript

จุดเด่นสำคัญคือ

  • Playwright-style API
  • Auto-waiting
  • Retry Assertion
  • Semantic Locator
  • Accessibility Tree
  • รองรับ iOS และ Android
  • รองรับ Simulator, Emulator และ Real Device
  • มี Inspector
  • มี HTML Report
  • รองรับ Parallel Test
  • รองรับ Projects
  • รองรับ Remote/Cloud Device
  • เหมาะสำหรับ CI/CD
  • มีแนวทางที่เอื้อต่อ AI Agent

อย่างไรก็ตาม Mobilewright ยังเป็น Framework ที่ใหม่กว่า Appium มาก ดังนั้นสำหรับระบบ Production ขนาดใหญ่ควรเริ่มจาก Proof of Concept (PoC) กับ Critical User Journey ก่อน เช่น Login, Checkout หรือ Payment แล้วจึงประเมินความเหมาะสมด้าน Device Support, Stability, CI/CD และ Ecosystem ก่อนขยายเป็น Full Regression Suite


#References

  1. Mobilewright Official Documentation
    https://mobilewright.dev/docs/

  2. Mobilewright GitHub
    https://github.com/mobile-next/mobilewright

  3. Writing Tests
    https://mobilewright.dev/docs/getting-started/writing-tests

  4. Running Tests
    https://mobilewright.dev/docs/getting-started/running-tests

  5. Locators
    https://mobilewright.dev/docs/guides/locators

  6. Assertions
    https://mobilewright.dev/docs/guides/assertions

  7. Windows Setup
    https://mobilewright.dev/docs/getting-started/windows