데이터 드리븐 UI 자동화 테스트 프레임워크 설계 및 구현

프레임워크 개요 및 아키텍처

UI 자동화 테스트의 유지보수성과 재사용성을 높이기 위해 페이지 객체 모델(Page Object Model, POM) 패턴을 기반으로 한 데이터 드리븐(Data-Driven) 프레임워크를 구축한다. 이 구조는 테스트 로직과 페이지 요소 정의를 분리하여, UI 변경 시 스크립트 전체를 수정할 필요 없이 페이지 클래스만 수정하면 되도록 설계되었다. 주요 특징은 다음과 같다.

  • 코드 모듈화: 엑셀 핸들링, 로깅, 설정 파일 파싱 등 공통 기능을 유틸리티로 캡슐화하여 중복 코드를 최소화한다.
  • 관심사의 분리: 테스트 데이터(엑셀), 요소 정의(설정 파일), 테스트 로직(스크립트)을 독립적으로 관리한다.
  • 실행 유연성: 데이터 소스를 통해 테스트 케이스를 제어하며, 다양한 시나리오를 손쉽게 추가할 수 있다.
  • 리포팅 및 디버깅: 테스트 실패 시 자동으로 스크린샷을 저장하고 상세 로그를 기록하여 원인 분석을 용이하게 한다.

디렉토리 구조

프레임워크는 기능별로 명확히 구분된 다음과 같은 디렉토리 구조를 갖는다.

  • Config: 전역 변수, 경로 설정, 로거 설정 등 환경 구성 파일을 포함한다.
  • TestData: 테스트 데이터가 담긴 엑셀 파일과 요소 식별자 정의 파일이 위치한다.
  • PageObjects: 각 웹 페이지를 클래스로 정의하며, 해당 페이지 내 요소 조작 메서드를 구현한다.
  • TestScripts: 실제 테스트 시나리오를 실행하는 진입점 스크립트가 위치한다.
  • Utils: 파일 입출력, 시간 처리, 스크린샷 캡처 등 공통 유틸리티 모듈을 관리한다.
  • Logs & Screenshots: 실행 중 생성되는 로그 파일과 실패 시 캡처된 이미지가 저장된다.

핵심 구현 상세

1. 요소 식별자 관리 (Config)

UI 요소의 locator를 코드에서 하드코딩하지 않고 별도의 INI 파일로 관리하여 유지보수성을 높인다.Locator의 종류(xpath, id 등)와 값을 구분자로 분리하여 저장한다.

PageLocators.ini 예시:

[UserLogin]
username_field = xpath > //input[@name='userId']
password_field = xpath > //input[@name='userPwd']
submit_btn = id > btnLogin

2. 전역 상수 정의 (Config)

프로젝트 내에서 반복적으로 사용되는 경로와 데이터 열 인덱스를 상수로 정의하여 관리한다. pathlib을 사용하여 운영체제 호환성을 확보한다.

from pathlib import Path

# 프로젝트 루트 경로
BASE_DIR = Path(__file__).resolve().parent.parent

# 파일 경로 설정
LOCATOR_FILE = BASE_DIR / "Config" / "PageLocators.ini"
DATA_SOURCE = BASE_DIR / "TestData" / "user_accounts.xlsx"

# 엑셀 데이터 열 매핑
SHEET_NAME = "Credentials"
COL_USER = 1
COL_PASS = 2
COL_RESULT = 3

3. 페이지 객체 구현 (PageObjects)

페이지 클래스는 웹 드라이버 인스턴스를 받아 초기화하며, 요소 정의 파일을 참조하여 액션을 수행하는 메서드를 제공한다. 이렇게 함으로써 UI 변경 시 페이지 클래스 코드만 수정하면 테스트 스크립트는 변경할 필요가 없어진다.

from selenium.webdriver.remote.webdriver import WebDriver
from Utils.config_parser import read_locator

class LoginPage:
    def __init__(self, driver: WebDriver):
        self.driver = driver

    def enter_username(self, text: str):
        strategy, value = read_locator("UserLogin", "username_field")
        element = self.driver.find_element(strategy, value)
        element.clear()
        element.send_keys(text)

    def enter_password(self, text: str):
        strategy, value = read_locator("UserLogin", "password_field")
        self.driver.find_element(strategy, value).send_keys(text)

    def click_submit(self):
        strategy, value = read_locator("UserLogin", "submit_btn")
        self.driver.find_element(strategy, value).click()

4. 유틸리티 모듈 (Utils)

설정 파일 파서: INI 파일에서 locator 정보를 읽어와 형식에 맞게 반환하는 헬퍼 함수를 구현한다.

import configparser

def read_locator(section: str, key: str) -> tuple:
    parser = configparser.ConfigParser()
    parser.read("Config/PageLocators.ini", encoding='utf-8')
    raw_value = parser.get(section, key)
    # "strategy > value" 형식을 파싱
    strategy, locator = raw_value.split(" > ", 1)
    return strategy.strip(), locator.strip()

스크린샷 캡처: 테스트 실패 시 현재 시간을 파일명으로 하여 스크린샷을 저장하는 기능을 구현한다.

import time
import os
from pathlib import Path

def save_screenshot(driver, name="error"):
    timestamp = time.strftime("%Y%m%d_%H%M%S")
    save_dir = Path("Screenshots")
    save_dir.mkdir(exist_ok=True)
    
    file_path = save_dir / f"{name}_{timestamp}.png"
    driver.save_screenshot(str(file_path))

5. 테스트 실행 흐름

TestScripts 디렉토리의 메인 실행 파일은 데이터 파일을 순회하며 테스트를 수행한다. 엑셀에서 데이터를 읽어와 페이지 객체의 메서드에 전달하고, 결과를 다시 엑셀에 기록하는 방식으로 동작한다. 예외 발생 시 save_screenshot 유틸리티를 호출하여 증거를 남긴다.

태그: Data-Driven Testing Page Object Model selenium python Test Automation Framework

8월 9일 09:11에 게시됨