접근성 기능 테스트
GitLab v19.5요약
axe-core-gem을 사용하는 기능 테스트는 가장 포괄적인 접근성 테스트 방식으로, 모든 UI 기술(HAML, Vue, JavaScript)에 걸친 전체 사용자 여정을 다룹니다. 다음 영역에 접근성 테스트를 우선 적용합니다:
접근성 테스트를 추가해야 하는 경우#
axe-core-gem을 사용하는 기능 테스트는 가장 포괄적인 접근성 테스트 방식으로, 모든 UI 기술(HAML, Vue, JavaScript)에 걸친 전체 사용자 여정을 다룹니다.
다음 영역에 접근성 테스트를 우선 적용합니다:
- 필수적인 사용자 여정: 사용자가 의존하는 핵심 워크플로.
- 트래픽이 많은 페이지: 사용자 상호작용이 많은 영역.
- 새 기능: 처음부터 접근성을 확보합니다.
- 복잡한 UI 상호작용: 여러 단계로 이루어진 절차, 모달, 동적 콘텐츠.
전략적 접근 방식#
가능한 모든 페이지 조합을 테스트하기보다 핵심 사용자 시나리오를 깊이 있게 다루는 데 집중합니다. 이 방식은 모든 뷰를 넓지만 얕게 다루는 것보다 더 큰 가치를 제공합니다.
기능 테스트로 검사할 때의 장점 중 하나는 개별 컴포넌트만이 아니라 여러 상태와 전체 사용자 흐름을 확인할 수 있다는 점입니다.
접근성 검사에 접근하는 방법의 예시는 아래에서 확인할 수 있습니다.
빈 상태#
일부 뷰에는 기본 뷰와 다른 페이지 구조로 이어지는 빈 상태가 있습니다. 빈 상태에서는 첫 이슈 생성이나 기능 활성화 같은 동작을 제공하기도 합니다. 이 경우 빈 상태와 기본 뷰 모두에 대한 단언을 추가합니다.
사용자 상호작용 전 준수 확인#
사용자가 수행할 것으로 예상되는 여러 단계를 대상으로 테스트하는 경우가 많습니다. 이때는 어떤 단계도 시뮬레이션되기 전에 검사를 일찍 포함해야 합니다. 이렇게 하면 사용자에게 기대하는 동작에 장벽이 없는지 확인할 수 있습니다.
변경된 페이지 구조 후 준수 확인#
사용자 상호작용으로 페이지 구조가 크게 바뀔 수 있습니다. 예를 들어 대화 상자가 표시되거나 새 섹션이 렌더링됩니다. 그런 경우에는 해당 변경 이후에 단언을 추가합니다. 사용자가 사용할 수 있는 모든 컴포넌트와 상호작용할 수 있어야 하기 때문입니다.
접근성 테스트를 추가하는 방법#
새 스펙 파일 생성#
자동화된 접근성 테스트에서는 다양한 사용자 여정에 대해 이미 정의된 단계를 따르려고 합니다. 이를 위해 E2E 테스트에 정의된 테스트 케이스를 재사용합니다.
황금 사용자 여정#
이미 정의된 황금 사용자 여정에 접근성 테스트 커버리지를 확보하려고 합니다. 이를 위해 Figma 파일을 접근성 스펙 생성에 사용할 수 있는 YAML 형식으로 변환했습니다.
이 스펙을 구현하는 방법은 Accessibility journeys README를 참고합니다.
특정 사용자 흐름#
담당 기능에 새 접근성 스펙을 추가하려면 다음 중 한 가지 방법으로 그룹의 테스트 케이스 목록을 살펴봅니다:
- 그룹의 레이블로 필터링할 수 있는 Test Cases 페이지를 확인합니다.
- E2E
browser_ui디렉터리와ee/browser_ui디렉터리로 이동한 뒤, 해당 스테이지의 디렉터리와 다루려는 기능을 선택합니다.
다룰 사용자 여정을 정했다면 다음을 수행합니다:
spec/features/accessibility로 이동합니다.- 해당 스테이지와 다루려는 기능의 폴더 아래에 새 Ruby 스펙을 만듭니다. 예를 들어
create/repository/입니다. - 따라가는 E2E 테스트 케이스의 이름을 따 파일 이름을 짓습니다. 예를 들어
add_new_branch_rule_spec.rb입니다.
이 예에서는 spec/features/accessibility/create/repository/add_new_branch_rule_spec.rb에 전용 기능 스펙이 만들어집니다.
다음 단계는 Capybara 기능 테스트 문법과 설정으로 테스트 케이스를 다시 작성하는 것입니다.
axe 메서드 사용#
Axe는 커스텀 매처 be_axe_clean을 제공하며 다음과 같이 사용할 수 있습니다:
# spec/features/accessibility/create/repository/add_new_branch_rule_spec.rb
it 'passes axe automated accessibility testing', :js do
visit_settings_page
# Wait for an element that appears only when this page is ready to scan.
expect(page).to have_selector('#content-body')
expect(page).to be_axe_clean
end
접근성 스캔을 위해 페이지를 준비할 때 wait_for_requests를 사용하지 않습니다. 이
메서드는 비동기 렌더링이 끝나기 전에 반환될 수 있어 스캔이 불완전해집니다.
대신 렌더링된 상태를 나타내는 페이지별 요소를 기다립니다.
wait_for_requests 또는 wait_for_all_requests를 사용하지 않습니다를 참고합니다.
필요하다면 within을 사용해 페이지의 특정 영역으로 테스트 범위를 좁힐 수 있습니다.
Axe는 다음과 같은 전용 절도 제공합니다:
expect(page).to be_axe_clean.within '[data-testid="element"]'
# run only WCAG 2.1 Level AA rules
expect(page).to be_axe_clean.according_to :wcag21aa
# specifies which rule to skip
expect(page).to be_axe_clean.skipping :'link-in-text-block'
# clauses can be chained
expect(page).to be_axe_clean.within('[data-testid="element"]')
.according_to(:wcag21aa)
Axe는 비활성 메뉴나 대화 상자처럼 숨겨진 영역은 테스트하지 않습니다. 숨겨진 영역의 접근성을 테스트하려면 해당 영역을 활성화하거나 보이도록 렌더링한 뒤 매처를 다시 실행하는 테스트를 작성합니다.
접근성 테스트는 기능 테스트 실행 방법과 동일하게 로컬에서 실행할 수 있습니다.
접근성 테스트를 추가한 뒤에는 가능한 모든 오류를 수정합니다.
수정 방법은 이 가이드를 참고합니다.
Pajamas 컴포넌트 문서의 접근성 섹션도 확인할 수 있습니다.
전역 변경이 필요한 오류가 있다면 후속 이슈를 만들고 accessibility, accessibility::intake 레이블을 지정합니다.
심각한 이슈만 대상으로 첫 테스트 추가#
기본적으로 be_axe_clean은 심각도와 관계없이 모든 위반에서 실패합니다.
기존 영역에 접근성 커버리지를 처음 추가하면 심각도가 낮은 위반이 한꺼번에 많이
드러날 수 있습니다.
커버리지를 점진적으로 도입하려면 with_minimum_impact를 연결해 특정 심각도 이상의
위반에서만 실패하도록 합니다.
Axe는 낮은 순서부터 minor, moderate, serious, critical의 네 가지 심각도를
보고합니다.
# Fail only on critical violations. Ignore serious, moderate, and minor violations.
expect(page).to be_axe_clean.within('#content-body').with_minimum_impact(
:critical, because: 'https://gitlab.com/gitlab-org/gitlab/-/issues/12345 - bootstrapping coverage'
)
because: 인자는 필수이며 비어 있으면 안 됩니다. 임계값은 실제 위반을 가리므로,
사용할 때마다 임계값을 완화하는 이유를 밝혀야 하며 추적 이슈 링크를 함께 두는 것이 좋습니다.
그 이유는 diff와 git blame, 코드 리뷰 과정에서 계속 확인할 수 있습니다.
with_minimum_impact는 커버리지를 처음 도입하는 동안에만 사용합니다.
critical 위반을 해결한 뒤에는 이 절을 제거해 모든 심각도를 다시 적용하거나,
임계값을 :serious로 낮춰 serious 위반까지 잡습니다.
모범 사례#
해당 제품 영역의 도메인 지식이 있으면 기능 테스트에 접근성 검사를 추가하기가 더 쉽습니다. 다만 접근성 테스트에 기여하는 데 도움이 되는 몇 가지가 있습니다.
페이지에서 접근성 테스트를 추가할 부분#
대부분의 경우 페이지 전체의 접근성을 테스트할 필요는 없습니다:
-
브레드크럼이나 메인 내비게이션처럼 모든 애플리케이션 뷰에 나타나는 요소가 있습니다. 이런 요소를 모든 기능 스펙에 포함하면 자원이 상당히 많이 들고, 한 번만 하면 되는 일을 여러 번 반복하게 됩니다. 이런 요소에는 자체 기능 스펙이 있으며 거기에서 테스트합니다.
-
기능 스펙이 뷰 전체를 다룬다면
<main id="content-body">요소로 범위를 좁히는 것이 모범 사례입니다. 다음은 그런 테스트 케이스의 예입니다:it "passes axe automated accessibility testing" do expect(page).to be_axe_clean.within('#content-body') end -
특정 테스트 케이스가 일부 컴포넌트를 포함한 섹션처럼 페이지의 일부만 다룬다면 테스트 범위를 그 섹션으로 유지합니다. 다음은 그런 테스트 케이스의 예입니다:
it 'passes axe automated accessibility testing for todo' do expect(page).to be_axe_clean.within(todo_selector) end
충분히 구체적이지 않은 테스트 출력#
axe 테스트 케이스가 실패하면 발견된 위반과 그 위반이 해당하는 요소를 출력합니다. Pajamas 컴포넌트를 자주 사용하기 때문에
그 요소가 요소를 식별하는 데 도움이 되는 주석 없이 <div>로만 나오는 경우가 많습니다. 다만 axe_core 규칙이
Ruby 테스트와 Deque 브라우저 확장인 axe DevTools 양쪽에 사용된다는 점을 활용할 수 있습니다. 두 도구는
같은 출력을 제공합니다.
- 사용하는 브라우저에 axe DevTools 확장이 설치되어 있는지 확인합니다. 자세한 내용은 axe DevTools 공식 웹사이트를 참고합니다.
- 기능 테스트로 검사하는 뷰로 이동합니다.
- axe DevTools 확장을 열고 페이지 스캔을 실행합니다.
- 발견된 이슈를 펼치고 Highlight 옵션으로 각 위반에 해당하는 페이지 요소를 확인합니다.
알려진 접근성 위반#
이 섹션에서는 권장 사항이 디자인 시스템과 다른 위반을 정리합니다:
link-in-text-block: 현재는skipping절로:'link-in-text-block'규칙을 건너뛰어 위반을 해결합니다. 이슈 1444에서 이 문제가 수정되고GlLink컴포넌트에 밑줄이 추가되면 이 절을 제거할 수 있습니다.