InfoGrab DocsInfoGrab Docs

접근성 기능 테스트

요약

axe-core-gem을 사용하는 기능 테스트는 가장 포괄적인 접근성 테스트 방식으로, 모든 UI 기술(HAML, Vue, JavaScript)에 걸친 전체 사용자 여정을 다룹니다. 다음 영역에 접근성 테스트를 우선 적용합니다:

접근성 테스트를 추가해야 하는 경우#

axe-core-gem을 사용하는 기능 테스트는 가장 포괄적인 접근성 테스트 방식으로, 모든 UI 기술(HAML, Vue, JavaScript)에 걸친 전체 사용자 여정을 다룹니다.

다음 영역에 접근성 테스트를 우선 적용합니다:

  • 필수적인 사용자 여정: 사용자가 의존하는 핵심 워크플로.
  • 트래픽이 많은 페이지: 사용자 상호작용이 많은 영역.
  • 새 기능: 처음부터 접근성을 확보합니다.
  • 복잡한 UI 상호작용: 여러 단계로 이루어진 절차, 모달, 동적 콘텐츠.

전략적 접근 방식#

가능한 모든 페이지 조합을 테스트하기보다 핵심 사용자 시나리오를 깊이 있게 다루는 데 집중합니다. 이 방식은 모든 뷰를 넓지만 얕게 다루는 것보다 더 큰 가치를 제공합니다.

기능 테스트로 검사할 때의 장점 중 하나는 개별 컴포넌트만이 아니라 여러 상태와 전체 사용자 흐름을 확인할 수 있다는 점입니다.

접근성 검사에 접근하는 방법의 예시는 아래에서 확인할 수 있습니다.

빈 상태#

일부 뷰에는 기본 뷰와 다른 페이지 구조로 이어지는 빈 상태가 있습니다. 빈 상태에서는 첫 이슈 생성이나 기능 활성화 같은 동작을 제공하기도 합니다. 이 경우 빈 상태와 기본 뷰 모두에 대한 단언을 추가합니다.

사용자 상호작용 전 준수 확인#

사용자가 수행할 것으로 예상되는 여러 단계를 대상으로 테스트하는 경우가 많습니다. 이때는 어떤 단계도 시뮬레이션되기 전에 검사를 일찍 포함해야 합니다. 이렇게 하면 사용자에게 기대하는 동작에 장벽이 없는지 확인할 수 있습니다.

변경된 페이지 구조 후 준수 확인#

사용자 상호작용으로 페이지 구조가 크게 바뀔 수 있습니다. 예를 들어 대화 상자가 표시되거나 새 섹션이 렌더링됩니다. 그런 경우에는 해당 변경 이후에 단언을 추가합니다. 사용자가 사용할 수 있는 모든 컴포넌트와 상호작용할 수 있어야 하기 때문입니다.

접근성 테스트를 추가하는 방법#

새 스펙 파일 생성#

자동화된 접근성 테스트에서는 다양한 사용자 여정에 대해 이미 정의된 단계를 따르려고 합니다. 이를 위해 E2E 테스트에 정의된 테스트 케이스를 재사용합니다.

황금 사용자 여정#

이미 정의된 황금 사용자 여정에 접근성 테스트 커버리지를 확보하려고 합니다. 이를 위해 Figma 파일을 접근성 스펙 생성에 사용할 수 있는 YAML 형식으로 변환했습니다.

이 스펙을 구현하는 방법은 Accessibility journeys README를 참고합니다.

특정 사용자 흐름#

담당 기능에 새 접근성 스펙을 추가하려면 다음 중 한 가지 방법으로 그룹의 테스트 케이스 목록을 살펴봅니다:

다룰 사용자 여정을 정했다면 다음을 수행합니다:

  • 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 위반까지 잡습니다.

모범 사례#

해당 제품 영역의 도메인 지식이 있으면 기능 테스트에 접근성 검사를 추가하기가 더 쉽습니다. 다만 접근성 테스트에 기여하는 데 도움이 되는 몇 가지가 있습니다.

페이지에서 접근성 테스트를 추가할 부분#

대부분의 경우 페이지 전체의 접근성을 테스트할 필요는 없습니다:

  1. 브레드크럼이나 메인 내비게이션처럼 모든 애플리케이션 뷰에 나타나는 요소가 있습니다. 이런 요소를 모든 기능 스펙에 포함하면 자원이 상당히 많이 들고, 한 번만 하면 되는 일을 여러 번 반복하게 됩니다. 이런 요소에는 자체 기능 스펙이 있으며 거기에서 테스트합니다.

  2. 기능 스펙이 뷰 전체를 다룬다면 <main id="content-body"> 요소로 범위를 좁히는 것이 모범 사례입니다. 다음은 그런 테스트 케이스의 예입니다:

     it "passes axe automated accessibility testing" do
       expect(page).to be_axe_clean.within('#content-body')
     end
    
  3. 특정 테스트 케이스가 일부 컴포넌트를 포함한 섹션처럼 페이지의 일부만 다룬다면 테스트 범위를 그 섹션으로 유지합니다. 다음은 그런 테스트 케이스의 예입니다:

     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 양쪽에 사용된다는 점을 활용할 수 있습니다. 두 도구는 같은 출력을 제공합니다.

  1. 사용하는 브라우저에 axe DevTools 확장이 설치되어 있는지 확인합니다. 자세한 내용은 axe DevTools 공식 웹사이트를 참고합니다.
  2. 기능 테스트로 검사하는 뷰로 이동합니다.
  3. axe DevTools 확장을 열고 페이지 스캔을 실행합니다.
  4. 발견된 이슈를 펼치고 Highlight 옵션으로 각 위반에 해당하는 페이지 요소를 확인합니다.

알려진 접근성 위반#

이 섹션에서는 권장 사항이 디자인 시스템과 다른 위반을 정리합니다:

  • link-in-text-block: 현재는 skipping 절로 :'link-in-text-block' 규칙을 건너뛰어 위반을 해결합니다. 이슈 1444에서 이 문제가 수정되고 GlLink 컴포넌트에 밑줄이 추가되면 이 절을 제거할 수 있습니다.

접근성 기능 테스트

GitLab v19.5
원문 보기

요약

axe-core-gem을 사용하는 기능 테스트는 가장 포괄적인 접근성 테스트 방식으로, 모든 UI 기술(HAML, Vue, JavaScript)에 걸친 전체 사용자 여정을 다룹니다. 다음 영역에 접근성 테스트를 우선 적용합니다:

접근성 테스트를 추가해야 하는 경우#

axe-core-gem을 사용하는 기능 테스트는 가장 포괄적인 접근성 테스트 방식으로, 모든 UI 기술(HAML, Vue, JavaScript)에 걸친 전체 사용자 여정을 다룹니다.

다음 영역에 접근성 테스트를 우선 적용합니다:

  • 필수적인 사용자 여정: 사용자가 의존하는 핵심 워크플로.
  • 트래픽이 많은 페이지: 사용자 상호작용이 많은 영역.
  • 새 기능: 처음부터 접근성을 확보합니다.
  • 복잡한 UI 상호작용: 여러 단계로 이루어진 절차, 모달, 동적 콘텐츠.

전략적 접근 방식#

가능한 모든 페이지 조합을 테스트하기보다 핵심 사용자 시나리오를 깊이 있게 다루는 데 집중합니다. 이 방식은 모든 뷰를 넓지만 얕게 다루는 것보다 더 큰 가치를 제공합니다.

기능 테스트로 검사할 때의 장점 중 하나는 개별 컴포넌트만이 아니라 여러 상태와 전체 사용자 흐름을 확인할 수 있다는 점입니다.

접근성 검사에 접근하는 방법의 예시는 아래에서 확인할 수 있습니다.

빈 상태#

일부 뷰에는 기본 뷰와 다른 페이지 구조로 이어지는 빈 상태가 있습니다. 빈 상태에서는 첫 이슈 생성이나 기능 활성화 같은 동작을 제공하기도 합니다. 이 경우 빈 상태와 기본 뷰 모두에 대한 단언을 추가합니다.

사용자 상호작용 전 준수 확인#

사용자가 수행할 것으로 예상되는 여러 단계를 대상으로 테스트하는 경우가 많습니다. 이때는 어떤 단계도 시뮬레이션되기 전에 검사를 일찍 포함해야 합니다. 이렇게 하면 사용자에게 기대하는 동작에 장벽이 없는지 확인할 수 있습니다.

변경된 페이지 구조 후 준수 확인#

사용자 상호작용으로 페이지 구조가 크게 바뀔 수 있습니다. 예를 들어 대화 상자가 표시되거나 새 섹션이 렌더링됩니다. 그런 경우에는 해당 변경 이후에 단언을 추가합니다. 사용자가 사용할 수 있는 모든 컴포넌트와 상호작용할 수 있어야 하기 때문입니다.

접근성 테스트를 추가하는 방법#

새 스펙 파일 생성#

자동화된 접근성 테스트에서는 다양한 사용자 여정에 대해 이미 정의된 단계를 따르려고 합니다. 이를 위해 E2E 테스트에 정의된 테스트 케이스를 재사용합니다.

황금 사용자 여정#

이미 정의된 황금 사용자 여정에 접근성 테스트 커버리지를 확보하려고 합니다. 이를 위해 Figma 파일을 접근성 스펙 생성에 사용할 수 있는 YAML 형식으로 변환했습니다.

이 스펙을 구현하는 방법은 Accessibility journeys README를 참고합니다.

특정 사용자 흐름#

담당 기능에 새 접근성 스펙을 추가하려면 다음 중 한 가지 방법으로 그룹의 테스트 케이스 목록을 살펴봅니다:

다룰 사용자 여정을 정했다면 다음을 수행합니다:

  • 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 위반까지 잡습니다.

모범 사례#

해당 제품 영역의 도메인 지식이 있으면 기능 테스트에 접근성 검사를 추가하기가 더 쉽습니다. 다만 접근성 테스트에 기여하는 데 도움이 되는 몇 가지가 있습니다.

페이지에서 접근성 테스트를 추가할 부분#

대부분의 경우 페이지 전체의 접근성을 테스트할 필요는 없습니다:

  1. 브레드크럼이나 메인 내비게이션처럼 모든 애플리케이션 뷰에 나타나는 요소가 있습니다. 이런 요소를 모든 기능 스펙에 포함하면 자원이 상당히 많이 들고, 한 번만 하면 되는 일을 여러 번 반복하게 됩니다. 이런 요소에는 자체 기능 스펙이 있으며 거기에서 테스트합니다.

  2. 기능 스펙이 뷰 전체를 다룬다면 <main id="content-body"> 요소로 범위를 좁히는 것이 모범 사례입니다. 다음은 그런 테스트 케이스의 예입니다:

     it "passes axe automated accessibility testing" do
       expect(page).to be_axe_clean.within('#content-body')
     end
    
  3. 특정 테스트 케이스가 일부 컴포넌트를 포함한 섹션처럼 페이지의 일부만 다룬다면 테스트 범위를 그 섹션으로 유지합니다. 다음은 그런 테스트 케이스의 예입니다:

     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 양쪽에 사용된다는 점을 활용할 수 있습니다. 두 도구는 같은 출력을 제공합니다.

  1. 사용하는 브라우저에 axe DevTools 확장이 설치되어 있는지 확인합니다. 자세한 내용은 axe DevTools 공식 웹사이트를 참고합니다.
  2. 기능 테스트로 검사하는 뷰로 이동합니다.
  3. axe DevTools 확장을 열고 페이지 스캔을 실행합니다.
  4. 발견된 이슈를 펼치고 Highlight 옵션으로 각 위반에 해당하는 페이지 요소를 확인합니다.

알려진 접근성 위반#

이 섹션에서는 권장 사항이 디자인 시스템과 다른 위반을 정리합니다:

  • link-in-text-block: 현재는 skipping 절로 :'link-in-text-block' 규칙을 건너뛰어 위반을 해결합니다. 이슈 1444에서 이 문제가 수정되고 GlLink 컴포넌트에 밑줄이 추가되면 이 절을 제거할 수 있습니다.