GUI에 대한 유지 보수가 아닌 부서지지 않는 단위 테스트를 작성하는 방법은 무엇입니까?


16

GUI 응용 프로그램에 대한 UI 단위 테스트를 작성하려고 시도했지만 처음 작성할 때 잘 작동하지만 부서지기 쉽고 디자인이 변경 될 때마다 (즉, 매우 자주) 깨지는 문제에 직면했습니다. GUI에 대한 유지 보수 가능한 단위 테스트를 유도하는 일련의 지침을 찾기 위해 고심하고 있습니다.

지금까지 내가 발견 한 한 가지는 "이 구성 요소는 입력 데이터를 어딘가에 표시해야합니다"라는 테스트가 훌륭하다는 것입니다 (그리고 HTML에서는 매우 쉽습니다). 구성 요소의 특정 부분의 특정 상태를 검사하는 테스트는 일반적으로 취약합니다. 사용자 행동을 따르고 기본적인 비즈니스 로직 (가장 중요한 부분)을 따르는 클릭 클릭 클릭 기대와 같은 테스트는 일반적으로 취하기 쉽습니다. 좋은 시험을 어떻게 작성합니까?


더 정확히 말하면, 나는에 대한 몇 가지 패턴을 알고 싶습니다 무엇을 내가 정확히, 내 UI에서 테스트 할 수있는 방법 을 테스트 할 수 있습니다. 명명 규칙과 고정 식별자는 좋지만 GUI가 많이 바뀌는 핵심 문제를 해결하지는 못합니다. 변경이 거의 불가능한 동작을 테스트하고 싶습니다. 테스트 할 올바른 것을 찾는 방법은 무엇입니까?


1
@MichaelDurrant : 원래 단위 테스트에 대해 물으면서 UI 테스트에 관한 질문을 편집했습니다. 통합 테스트를 유지하기가 더 어려우며 가능할 때마다 단위 테스트를 선호합니다.
mik01aj

2
나는 이것이 문제의 일부라고 생각하지만, 근본적으로 그들의 raison d' etre가 무언가에 인터페이스하는 것이므로 단위 테스트만으로 인터페이스를 실제로 테스트 할 수는 없습니다. GUI는 이와 관련하여 다르지 않습니다.
jk.

m01, 다시 변경할 수 있습니다. UI 테스트는 일반적으로 통합 테스트라고 생각합니다. 테스트는 현재 존재하는 시드 및 픽스처 데이터와이를 사용하는 UI에 의존하는 경향이 있습니다. 뛰어난 다른 데이터에 의존하지 않는 진정한 UI 테스트가있는 경우. 그러나 나는 이것이 비교적 드문 것으로 나타났습니다.
Michael Durrant

2
관련 그러나이 이후되지 중복은 GUI를 테스트에 관한 것입니다 : programmers.stackexchange.com/questions/109703/...
K3B

답변:


3

GUI 테스트의 일반적인 문제 ... 이러한 테스트가 취하기 쉬운 주된 이유 는 요구 사항의 변경이 아닌 GUI의 변경에서 살아남을 수 없기 때문 입니다. GUI의 변경 사항이 테스트의 단일 위치에 격리되도록 테스트 코드를 구조화해야합니다.

예를 들어 다음과 같은 테스트를 생각해보십시오.

사용자가 전화 번호 필드에 '999'를 입력하고 저장 버튼을 클릭하면 오류 메시지 팝업에 '잘못된 전화 번호'가 표시되어야합니다.

유효성 검사 요구 사항이 유지되는 경우에도 인터페이스를 다시 작업 할 때이 테스트를 수행 할 수있는 충분한 공간이 있습니다.

자, 이것을 약간의 다른 말로 표현해 보자.

사용자가 전화 번호로 '999'를 입력하고 프로필 페이지를 저장하면 '잘못된 전화 번호'라는 오류가 표시됩니다

테스트는 동일하지만 요구 사항은 동일하지만 이러한 종류의 테스트는 UI의 성형 수술 후에도 지속됩니다. 분명히 코드를 변경해야하지만 코드는 격리됩니다. 프로파일 페이지에 대해 이러한 테스트가 10 개 또는 20 개이고 오류 메시지 표시 유효성 검증 논리를 javascript-alerts에서 jquery-popups로 이동하더라도 오류 메시지를 확인하는 단일 테스트 부분 만 변경하면됩니다.


4

이것은 일반적인 문제입니다. 나는주의를 기울일 것이다 :

  • 요소 이름을 지정하는 방법

    css id 또는 class를 사용하여 요소를 식별하십시오. 객체가 고유 할 때 CSS ID를 사용하는 것이 좋습니다. 예를 들어 Ruby on Rails와 같이 사용중인 프레임 워크를 고려하면 name속성이 자동으로 할당되며 CSS ID 또는 클래스를 사용하는 것보다 (직관적이지 않게) 더 좋을 수 있습니다

  • 요소를 식별하는 방법

    같은 위치 식별자 피 table/tr/td/td같은 형태의 찬성 td[id="main_vehicle"또는 td[class='alternates']. 적절한 경우 데이터 속성 사용을 고려하십시오. 더 나은 등을 피하기 레이아웃 태그하려고 <td>아예 그래서 위의 어느 스팬 및 사용하는 것이, 예를 들어 추가 할 수 있습니다 위해 <span id="main_vehicle">또는 같은 와일드 카드 선택 *[id="main_vehicle"](가) 어디에 *지금 사업부, 스팬, TD 등이 될 수를

  • QA 및 테스트에만 사용되는 테스트 특정 데이터 속성 사용

  • 요소에 대한 불필요한 자격을 피하십시오. 다음을 사용하여 자신을 찾을 수 있습니다.

    body.main div#vehicles > form#vehicle input#primary_vehicle_name

    그러나이를 위해서는 입력 필드가 정확한 차량 ID를 가진 양식으로 유지되고 본문 클래스가있는 본문이있는 페이지와 차량 ID가있는 차량이있는 div가 차량. 해당 구조 및 테스트가 변경되면 중단됩니다. 이 경우에는

    input#primary_vehicle_name

    요소를 고유하게 식별하기에 충분합니다.

  • 보이는 텍스트를 나타내는 테스트를 피하십시오. 사용자에게 표시되는 페이지의 텍스트는 일반적으로 사이트가 유지 관리되고 업데이트 될 때 시간이 지남에 따라 변경되므로 css id 및 css 클래스 또는 데이터 속성과 같은 식별자를 사용하십시오. 같은 요소 form, input그리고 select형태의 사용은 일반적으로 예를 들어, ID 또는 클래스와 함께, 또한 식별 요소의 좋은 부분이다 li.vehicle또는 input#first-vehicle 당신은 또한 예를 들어, 자신의 식별자를 추가 할 수 있습니다 <div data-vehicle='dodge'>. 이런 식으로 개발자와 디자이너가 변경할 수있는 요소 ID 또는 클래스를 사용하지 않아도됩니다. 나는 시간이 지남에 따라 개발자와 디자이너와 함께 일하고 이름과 범위를 합의하는 것이 더 낫다는 것을 알았습니다. 그것은 어렵다.

  • 고정 데이터 유지 관리 방법

    실제 요소를 식별하는 것과 유사하게 변수 나 메소드로 유지되어 재사용되고 중앙에서 유지 될 수있는 작은 텍스트 조각 인 페이지 개체를 위해 값을 식별하는 인라인 하드 코딩 된 선택기를 사용하지 마십시오. 하드 코딩 된 값에 대해이 패턴을 따르는 Javascript 변수의 예 :

    storedVars["eqv_auto_year"] = "2015";
    storedVars["eqv_auto_make_1"] = "ALFA ROMEO";
    storedVars["eqv_auto_make_2"] = "HONDA";`  
    

    셀레늄 위키셀레늄 문서의 페이지 개체에 대한 추가 정보

  • 개발자와의 커뮤니케이션.

    워크 플로 문제인 '개발자가 변경하고 QA 자동화를 중단하는'측면에서 기술적 인 접근 방식에 관계없이. 다음 사항을 확인해야합니다. 모든 사람이 동일한 팀입니다. 개발자는 동일한 통합 테스트를 실행합니다. 표준이 합의되고 두 그룹이 뒤 따릅니다. 완료의 정의에는 UI 테스트 실행 및 업데이트가 포함됩니다. 개발자와 테스터는 테스트 계획을 수립하고 티켓 정리 (Agile을 수행하는 경우)에 참석하고 정리의 일부로 UI 테스트에 대해 이야기합니다. 이름 지정에 사용하는 모든 접근 방법과 전략이 응용 프로그램 개발자와 조정되어 있는지 확인해야합니다. 같은 페이지에 표시되지 않으면 객체 이름 지정과 충돌하는 것이 좋습니다. 루비 프로젝트를 위해 최근에 만든 페이지 객체 메소드의 몇 가지 예 :

    def css_email_opt_in_true
      'auto_policy[email_opt_in][value=1]'
    end 
    
    def css_phone_opt_in
      '*[name="auto_policy[phone_opt_in]"]'
    end 
    
    def css_phone_opt_in_true
      'input[name=phone_opt_in][value=true]'
    end 
    
    def css_credit_rating
      'auto_policy[credit_rating]'
    end
    

    다음은 자바 스크립트 변수와 동일한 페이지 객체입니다.

    storedVars["css_email_opt_in"] = "css=*[name='auto_policy[email_opt_in]']";
    storedVars["css_phone_opt_in"]="css=*[name='auto_policy[phone_opt_in]']";
    storedVars["css_phone_opt_in_true"]="css=input[name='phone_opt_in'][value=true]";
    storedVars["css_credit_rating"]="css=select[name='auto_policy[credit_rating]']";
    

2
이것들은 유용한 힌트이며, 실제로 이미 대부분을 따르고 있습니다. 내 문제는 일부 버튼에 대한 테스트를 작성한 다음 동일한 작업이 다른 곳에서 처리되는 동안이 버튼이 제거된다는 것입니다. 또는 버튼은 그대로 유지되지만 레이블이 변경되고 버튼이 추가 작업을 실행합니다.
mik01aj

1
아, 그거 알아요. 그래, 그 작업을 위해 나는 워크 플로와 조직의 QA 개발자 상호 작용에 중점을 둘 것입니다
Michael Durrant

1
또한 귀하의 질문을 찾은 사람을 위해 정보를 게시하고 있으며 귀하가 가지고 있거나 알지 못하는 부분이 모두 없을 수도 있습니다.
Michael Durrant

1
귀하의 의견을 바탕으로 마지막 불렛 포인트를 확장했습니다.
Michael Durrant

1
그리고 요소의 이름을 지정하고 식별하고 보이는 텍스트를 사용하지 않는 것에 대한 부분을 업데이트했습니다.
Michael Durrant

3

사람들이 MVC, MVP, 발표자 등을 먼저 개발 한 이유와 유사한 디자인 패턴은 비즈니스 로직과 사용자 인터페이스를 분리하기위한 것이 었습니다.

분명히 뷰 부분은 프로그램을 시작하고 보여지는 내용을 확인해야만 테스트 할 수 있습니다. 즉, 승인 테스트에서만 테스트 할 수 있습니다.

반면에 비즈니스 로직 테스트는 단위 테스트에서 수행 할 수 있습니다. 이것이 귀하의 질문에 대한 답변입니다. 모델의 모든 것을 테스트하고 가능하면 컨트롤러 코드를 테스트 할 수도 있습니다.


GUI가 많이 바뀐다

요구 사항을 변경 한 경우에만 발생할 수 있습니다. 요구 사항이 변경되면 코드를 수정하는 것 외에 다른 방법은 없습니다. 훌륭한 디자인과 아키텍처를 만들면 많은 곳에서 변경 사항이 전파되지 않습니다.


2
좋은 지적이라고 생각합니다. 어쩌면 나는 MVC를 잘못하고있을 것입니다 :) Btw, 많은 사용자를위한 웹 플랫폼을 개발할 때 요구 사항 변경이 불가피하다고 생각합니다. GUI 사용을 시작하기 전까지는 사용자의 행동 방식을 모릅니다.
mik01aj

2

GUI 상호 작용 테스트는 다른 종류의 테스트보다 덜 취해야합니다. 그건; 애플리케이션이 어떤 식 으로든 변경되는 경우이를 반영하도록 테스트를 업데이트해야합니다.

비교하자면 :

단위 테스트

원본 : 예외 validateEmail()InvalidData발생합니다. 이것은 단위 테스트에서 올바르게 다루어집니다.

변경 : 예외 validateEmail()InvalidEmail발생합니다. 이제 테스트가 올바르지 않고 업데이트되었으며 모든 것이 다시 녹색입니다.

GUI 테스트

원본 : 잘못된 이메일을 입력하면 "잘못된 데이터 입력"이 포함 된 팝업 오류 상자가 나타납니다. 테스트에서 올바르게 감지되었습니다.

변경 : 잘못된 이메일을 입력하면 "잘못된 이메일을 입력했습니다"라는 인라인 오류가 발생합니다. 이제 테스트가 올바르지 않고 업데이트되었으며 모든 것이 다시 녹색입니다.


입력과 출력 (잘 정의 된 동작)을 테스트하고 있음을 기억하십시오. GUI 테스트인지, 단위 테스트인지, 통합 테스트인지에 관계없이

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.