CupCode.cc
Section 03 · Module 07 · Lesson 01 · ~15-20 นาที

รูปแบบโครงสร้าง Automation Project

เวลาเรียน: 15-20 นาที ต้องรู้มาก่อน: Module 06 รูปแบบ: อ่าน + แบบฝึกสั้น ๆ

จบบทนี้แล้วคุณจะ...

  • อธิบายได้ว่าโครงสร้าง project ที่ดีมีลักษณะอย่างไร
  • รู้จัก folder organization มาตรฐาน (tests/, pages/, fixtures/, utils/)
  • เข้าใจ Page Object Model (POM) ในระดับ concept
  • เข้าใจหลัก separation of concerns ใน automation
  • จัดโครงสร้าง project ให้เป็นระเบียบได้
1 · ทำไมโครงสร้าง project ถึงสำคัญ

ลองนึกภาพ automation project ที่มี test 300 ไฟล์:

แบบไม่มีโครงสร้าง:

project/
├── test1.js
├── test2.js
├── test_login.js
├── helper.js
├── test_cart_new.js
├── test_cart_old.js
├── utils.js
├── more_utils.js
├── login_page.js
├── test3_FINAL.js
├── test3_FINAL_v2.js
├── ...อีก 290 ไฟล์...

คุณจะหาว่า test ไหนทดสอบอะไร? code ที่ใช้ร่วมกันอยู่ตรงไหน? ไฟล์ไหนที่ยังใช้อยู่?

แบบมีโครงสร้าง:

project/
├── tests/
│   ├── auth/
│   │   ├── login.test.js
│   │   └── registration.test.js
│   ├── cart/
│   │   ├── add-to-cart.test.js
│   │   └── checkout.test.js
│   └── search/
│       └── product-search.test.js
├── pages/
│   ├── login.page.js
│   ├── cart.page.js
│   └── search.page.js
├── fixtures/
│   ├── users.json
│   └── products.json
├── utils/
│   ├── api-helper.js
│   └── date-helper.js
└── config/
    ├── dev.config.js
    └── staging.config.js

แค่ดูโครงสร้าง ก็รู้ทันทีว่าอะไรอยู่ตรงไหน

2 · Folder Organization มาตรฐาน

tests/

  • เก็บ test files ทั้งหมด จัดกลุ่มตาม feature/module
  • ตั้งชื่อไฟล์ให้บอกว่าทดสอบอะไร เช่น login.test.js
  • จัดกลุ่มตาม feature: tests/auth/, tests/cart/, tests/payment/

pages/ (หรือ page-objects/)

  • เก็บ Page Object files ที่ wrap การทำงานของแต่ละหน้า
  • แต่ละไฟล์แทนหนึ่งหน้า/component เช่น login.page.js
  • เก็บ locators และ actions ของหน้านั้น

fixtures/

  • เก็บ test data ที่เป็น static
  • JSON, CSV, หรือ format อื่น ๆ
  • เช่น: test users, product catalogs, expected results

utils/ (หรือ helpers/)

  • เก็บ utility functions ที่ใช้ร่วมกันหลาย test
  • เช่น: date formatting, API helpers, data generators

config/

  • เก็บ configuration files สำหรับแต่ละ environment
  • Base URL, credentials path, timeout settings
3 · Page Object Model (POM) — Concept Level

ปัญหาที่ POM แก้

สมมติคุณมี 20 test ที่ต้อง login ทุก test มี code แบบนี้:

// ใน test ที่ 1
หา element "#username" แล้วพิมพ์ "admin"
หา element "#password" แล้วพิมพ์ "pass123"
หา element "#login-btn" แล้วคลิก

// ใน test ที่ 2 (copy มาเหมือนกัน)
หา element "#username" แล้วพิมพ์ "admin"
หา element "#password" แล้วพิมพ์ "pass123"
หา element "#login-btn" แล้วคลิก

// ...อีก 18 test...

ถ้าวันหนึ่ง dev เปลี่ยน #username เป็น #email → ต้องแก้ 20 ที่!

POM คืออะไร

Page Object Model คือแนวคิดที่ แยก locators และ actions ของแต่ละหน้า ออกจาก test logic

// LoginPage (page object)
- locator: username = "#username"
- locator: password = "#password"
- locator: loginBtn = "#login-btn"
- action: login(user, pass) = พิมพ์ username, พิมพ์ password, คลิก loginBtn

// Test (ใช้ page object)
loginPage.login("admin", "pass123")

ถ้า dev เปลี่ยน #username เป็น #email → แก้แค่ที่เดียวใน LoginPage

ประโยชน์ของ POM

  1. DRY (Don't Repeat Yourself) — locators อยู่ที่เดียว ไม่ duplicate
  2. Easy maintenance — UI เปลี่ยน แก้แค่ page object ไม่ต้องแก้ test
  3. Readable tests — test อ่านเข้าใจง่ายเพราะเรียก action ที่มีความหมาย
  4. Reusable — หลาย test ใช้ page object เดียวกันได้
4 · Separation of Concerns

แต่ละส่วนของ automation project ควรรับผิดชอบเรื่องเดียว:

Layer รับผิดชอบ ตัวอย่าง
Test ลำดับขั้นตอนและ assertions "login → เพิ่มสินค้า → เช็คตะกร้า"
Page Object Locators และ actions ของแต่ละหน้า "หา element, คลิก, พิมพ์"
Fixtures Test data "user: admin, pass: 123"
Utils Helper functions ที่ไม่ผูกกับหน้าใดหน้าหนึ่ง "format date, generate random email"
Config Environment settings "base URL, timeout, browser"

ทำไมต้องแยก?

  • เปลี่ยน UI → แก้แค่ page objects
  • เปลี่ยน test data → แก้แค่ fixtures
  • เปลี่ยน environment → แก้แค่ config
  • เพิ่ม test case → เขียนแค่ test file ใหม่ โดยใช้ page objects + fixtures ที่มีอยู่
5 · Config Management

สิ่งที่ควรอยู่ใน config

  • Base URL ของ application
  • Browser ที่จะใช้ test (Chrome, Firefox, etc.)
  • Timeout settings (default wait, page load timeout)
  • Screenshot/video path สำหรับ failure
  • Parallel execution settings
  • Reporter settings (HTML report, JUnit XML)

สิ่งที่ไม่ควรอยู่ใน config (หรือ code)

  • Passwords / API keys → ใช้ environment variables
  • Personal data → ใช้ fixtures ที่ generate
  • Hardcoded waits → ใช้ config timeout
แบบฝึก: จัดโครงสร้าง Project

โจทย์

คุณได้รับ automation project ที่มีไฟล์ดังนี้ (ไม่มีโครงสร้าง):

my-project/
├── test_login_success.js
├── test_login_fail.js
├── test_add_to_cart.js
├── test_remove_from_cart.js
├── test_checkout_credit.js
├── test_checkout_cod.js
├── test_search_product.js
├── test_filter_by_price.js
├── login_helpers.js
├── cart_helpers.js
├── search_helpers.js
├── checkout_helpers.js
├── test_users.json
├── test_products.json
├── test_credit_cards.json
├── date_utils.js
├── api_utils.js
├── email_utils.js
├── config_dev.js
├── config_staging.js
├── config_prod.js

จัดโครงสร้างใหม่ให้เป็นระเบียบ

ดูคำตอบแนะนำ
my-project/
├── tests/
│   ├── auth/
│   │   ├── login-success.test.js
│   │   └── login-fail.test.js
│   ├── cart/
│   │   ├── add-to-cart.test.js
│   │   └── remove-from-cart.test.js
│   ├── checkout/
│   │   ├── checkout-credit.test.js
│   │   └── checkout-cod.test.js
│   └── search/
│       ├── search-product.test.js
│       └── filter-by-price.test.js
├── pages/
│   ├── login.page.js          ← จาก login_helpers.js
│   ├── cart.page.js            ← จาก cart_helpers.js
│   ├── search.page.js          ← จาก search_helpers.js
│   └── checkout.page.js        ← จาก checkout_helpers.js
├── fixtures/
│   ├── users.json              ← จาก test_users.json
│   ├── products.json           ← จาก test_products.json
│   └── credit-cards.json       ← จาก test_credit_cards.json
├── utils/
│   ├── date-helper.js          ← จาก date_utils.js
│   ├── api-helper.js           ← จาก api_utils.js
│   └── email-helper.js         ← จาก email_utils.js
└── config/
    ├── dev.config.js
    ├── staging.config.js
    └── prod.config.js

หลักการที่ใช้:

  1. tests/ จัดกลุ่มตาม feature (auth, cart, checkout, search)
  2. pages/ เปลี่ยนจาก "helpers" เป็น page objects — แต่ละไฟล์แทนหนึ่งหน้า
  3. fixtures/ รวม test data ไว้ที่เดียว ตั้งชื่อให้ชัดเจน
  4. utils/ เก็บ helpers ที่ไม่ผูกกับหน้าใดหน้าหนึ่ง
  5. config/ แยก config ตาม environment
  6. Naming: ใช้ kebab-case, เติม .test.js / .page.js เพื่อบอกประเภท

สิ่งที่ต้องเอาติดตัวไปจากบทนี้

  • โครงสร้างที่ดี ทำให้หาไฟล์ง่าย, maintain ง่าย, onboard คนใหม่ง่าย
  • Page Object Model แยก locators/actions ออกจาก test logic — UI เปลี่ยน แก้ที่เดียว
  • Separation of concerns — test, page object, fixture, utils, config แต่ละส่วนรับผิดชอบเรื่องเดียว
  • จัดกลุ่มตาม feature ไม่ใช่ตามประเภทไฟล์ — ง่ายต่อการหาและ maintain
  • โครงสร้างที่ดีตั้งแต่ต้น ประหยัดเวลามหาศาล เมื่อ project โตขึ้น