페이지 상호작용에 사용되는 클라이언트 기능과 스크립트 주입

테스트 페이지에서 사용자 정의 자바스크립트 코드를 실행하는 방법, 코드에서 페이지 모델 같은 대상을 사용하는 방법, 브라우저에서 임의의 이벤트를 기다리는 방법, 프로그램이나 JS 모듈 전체를 실행하는 가장 빠른 방법을 배울 것입니다.
사용자와 응용 프로그램의 상호작용 방식을 끝까지 테스트합니다.이론적으로 이런 상호작용은 간단한 조작을 포함한다. 예를 들어 마우스 클릭 요소, 버튼, 드래그 또는 파일 업로드 등이다.TestCafe API를 사용하면 코드를 사용하여 이러한 기본 작업을 수행할 수 있습니다.그러나 현실 세계의 응용 프로그램은 정적 입력 폼보다 더 복잡하다.테스트 페이지와 더욱 긴밀한 상호작용을 하지 않으면 일부 응용 프로그램은 테스트를 할 수 없습니다.본고에서 우리는 몇 가지 예시를 되돌아보고 TestCafe 내부 구조의 지식이 클라이언트 기능과 스크립트 주입의 도움으로 복잡하거나 디자인이 엉망인 페이지를 테스트하는 데 어떻게 도움을 주는지 보여 준다.

클라이언트 함수를 사용하여 브라우저에서 코드 실행


원소를 눌러야 하는데 디자인이나 실현된 선택으로 인해 같은 페이지의 다른 원소가 첫 번째 원소와 중첩된다고 가정하십시오.호출t.click만 하면 TestCafe는 대상 요소가 전경에 나타날 때까지 기다립니다.미리 정의된 시간 초과가 만료되면 TestCafe는 결국 중첩 요소를 클릭합니다.만약 테스트 작성자가 클릭할 의사가 있다면, 테스트는 성공적으로 완성될 것이다.그러나 시간 초과 시간은 목적 없는 기다림에 낭비됐다.다음 코드를 실행하면 중첩 요소를 숨기고 일시 중지를 방지할 수 있습니다.
test('Hide element', async t => {
    const hideElement = ClientFunction(() => {
        document.querySelector('#id').style.display = 'none';
    });
 
    await hideElement();
 
    await t.expect(Selector('#id').visible).notOk();
});
코드를 업데이트하고 요소 ID를 변수에 저장하려는 경우도 있습니다.
test('Hide element', async t => {
    const elementId = '#id';
    const hideElement = ClientFunction(() => {
        document.querySelector(elementId).style.display = 'none';
    });
 
    await hideElement();
 
    await t.expect(Selector(elementId).visible).notOk();
});
변수는 좋은 생각입니다. 사용할 수 있지만 이런 식으로 사용할 수 없습니다.위의 테스트는 실패하고 오류가 발생합니다.
My Fixture
 × Hide element
   1) An error occurred in ClientFunction code:
      ReferenceError: elementId is not defined
겉으로 보기에, 당신의 자바스크립트 프로그래밍 경험이 테스트가 매우 좋다는 것을 알려줄 수도 있습니다.Test Cafe의 기본 메커니즘을 더 자세히 살펴보고 테스트가 실패한 원인을 살펴봅시다.

엔진 덮개


TestCafe는 클라이언트 아키텍처를 기반으로 합니다.테스트 코드가 노드에서 실행됩니다.js 처리 (서버) 및 프록시 서버와 브라우저 (클라이언트) 상호작용을 사용합니다.

이 사실을 감안하면 당신은 다음과 같이 예상할 수 있다.
  • 테스트 코드는 브라우저 상하문에 직접 접근할 수 없습니다.
  • Test Cafe는 브라우저와 비동기적으로 상호작용한다(이것이 바로 GitHub과 Stack Overflow에서 자주 결여await문제를 발표하는 이유이다).
  • 서버측 TestCafe 프로세스와 클라이언트 브라우저는 서열화된 데이터만 교환할 수 있습니다.
  • 다음과 같이 TestCafe의 클라이언트 - 서버 상호 작용을 단순화할 수 있습니다.
  • 서버에서 TestCafe API는 브라우저에서 조작과 사용자 코드를 실행하는 방법을 공개했다.API를 트리거하면 TestCafe가 명령을 생성하여 에이전트에 전달합니다: TestCafe Hammerhead.
  • TestCafe Hammerhead는 서버에서 브라우저로 명령을 전송하고 결과가 준비될 때 반환합니다.
  • 클라이언트에서 TestCafe 스크립트는 이 명령을 수신하고 브라우저가 사용자의 동작을 처리하는 것과 같은 방식으로 명령을 실행한다.
  • 클라이언트 함수에 변수 전달


    클라이언트에서 매개 변수화 함수를 만들거나 페이지 모델 속성을 사용합니다.
    변수를 도입하려고 했지만 실패한 코드로 돌아갑니다.
    test('Hide element', async t => {
        const elementId = '#id'; 
        const hideElement = ClientFunction(() => {
            document.querySelector(elementId).style.display = 'none';
        });
     
        await hideElement();
     
        await t.expect(Selector(elementId).visible).notOk();
    });
    
    이 기능은 브라우저에서 실행되어야 합니다.앞에서 말한 바와 같이, 서열화된 데이터만 클라이언트와 서버 사이에서 전송할 수 있다.이것이 바로 TestCafe가 이 함수를 문자열로 서열화하는 이유입니다.그런 다음 브라우저에서 문자열을 받을 때 문자열을 계산합니다.이제 클라이언트 함수에 왜 클로즈업이 적용되지 않는지 알 수 있습니다.
    그렇다면 해결책은 무엇일까?TestCafe에서 함수를 문자열로 변환하기 전에, 단독 서열화 프로그램 모듈은 ClientFunction() 에 전달된 매개 변수를 처리합니다.이것은 클라이언트와 서버 간에 전송된 모든 데이터를 서열화한 같은 모듈이다.이것은 매개 변수를 클라이언트 함수에 쉽게 전달할 수 있고 안전하게 도착할 수 있다는 것을 의미한다.
    또한 ClientFunction 구조 함수에 전달할 수 있는 옵션에서 dependencies 속성을 찾을 수 있습니다.
    TestCafe는 테스트 코드에 명시된 변수에 액세스하는 두 가지 옵션을 제공합니다.
    첫 번째 옵션은 변수를 매개변수로 전달하는 것입니다.
    test('Hide element', async t => {
        const elementId = '#id';
     
        const hideElement = ClientFunction(targetId => {
            document.querySelector(targetId).style.display = 'none';
        });
     
        await hideElement(elementId);
     
        await t.expect(Selector(elementId).visible).notOk();
    });
    
    그러나 요소에 ID가 없어 DOM 트리에서 쉽게 찾을 수 없는 경우 어떻게 해야 합니까?두 번째 옵션은 선택기를 클라이언트 함수에 전달하는 것입니다.ClientFunction 구조 함수의 dependencies 옵션을 사용합니다.
    test('Hide element', async t => {
        const elementSelector = Selector('#populate');
     
        const hideElement = ClientFunction(() => {
            elementSelector().style.display = 'none';
        }, { dependencies: { elementSelector } });
     
        await hideElement();
     
        await t.expect(elementSelector.visible).notOk();
    });
    
    클라이언트 함수와 선택기는 공통점이 많습니다.선택기를 만들고 실행하는 방법은 클라이언트 함수에서 나온 유사한 방법입니다.복잡한 선택기 조회를 실행하려면 클라이언트 함수처럼 함수를 Selector 구조 함수에 전달할 수 있습니다.그것들 사이의 주요 차이점은 되돌아오는 유형에 있다.선택기는 DOMNode 를 되돌려야 하고, 클라이언트 함수는 서열화된 값을 되돌려주거나, 이 값으로 해석할 수 있는 약속을 되돌려야 한다.

    사용자 지정 기준 대기


    TestCafe에서 페이지를 로드할 시기를 지정할 수 있습니다.
    이제 클라이언트 함수가 약속을 되돌려 주기를 바라는 이유를 살펴봅시다.
    TestCafe는 테스트가 시작되기 전에 대기DOMContentLoadedload 이벤트, 그리고 XHR 요청(후자는 3초 허용)으로 설계되었다.페이지의 모든 스크립트를 초기화하기 전에 대기 시간이 끝날 수도 있습니다.다음 클라이언트 함수는 사용자 정의 조건이 충족될 때까지 테스트를 중지합니다. (사용자 스크립트로 지시기를 완성할 수 있습니다.)
    test('Wait for scripts', async t => {
        const waitForScripts = ClientFunction(waitTimeout => {
            function checkCondition () {
                // Replace this line with a custom condition.
                return true;
            }
            return new Promise((resolve, reject) => {
                var timeout, interval;
                timeout = setTimeout(() => {
                    clearInterval(interval);
                    reject('Timeout is exceeded.');
                }, waitTimeout);
                interval = setInterval(() => {
                    if (checkCondition()) {
                        clearTimeout(timeout);
                        clearInterval(interval);
                        resolve();
                    }
                }, 100);
            });
        });
        await waitForScripts(2000);
    });
    
    브라우저가 Promises를 지원하지 않더라도, 이 클라이언트 함수는 TestCafe가 코드를 처리할 때 필요한 다각형 채우기를 자동으로 추가하기 때문에 작업을 할 수 있습니다.

    코드를 영구적으로 추가하기 위해 스크립트 주입


    필요할 때 클라이언트 함수는 테스트 페이지와 상호작용에 사용할 수 있습니다.클라이언트 함수를 변수에 저장하지 않고 실행할 수도 있습니다.단, 방향을 바꾸거나 페이지를 다시 불러오면 이 함수에서 테스트 페이지에서 변경한 모든 내용을 복원합니다.페이지를 영구적으로 수정하려면 클라이언트 스크립트를 테스트 페이지에 주입하십시오.주입된 스크립트가 <head> 표시에 추가되었습니다.

    전체 테스트 과정에서 지속적으로 존재하는 스크립트


    배너를 숨기거나 요소의 속성을 수정해야 하는 경우 개별 파일에서 클라이언트 코드를 구성할 수 있습니다.
    각본js
    window.addEventListener('DOMContentLoaded',function(){
        constelement=document.querySelector('your-selector');
        element.setAttribute('foo-bar','baz');
    });
    
    그런 다음 원하는 API를 사용하여 모든 테스트에 이 파일을 첨부합니다(중복 제거beforeEach.
    명령줄 인터페이스
    testcafe chrome test.js --client-scripts script.js
    
    미국 석유 학회
    runner.clientScripts('script.js');
    
    프로파일
    {  
        "clientScripts": "script.js"
    }
    

    주입된 스크립트가 먼저 실행됨


    TestCafe는 페이지의 다른 스크립트 이전에 실행될 수 있도록 주입된 스크립트를 자동화 코드에 추가합니다.따라서 주입 스크립트를 사용하여 페이지의 행동을 변경할 수 있습니다.예를 들어, 다음 그림과 같이 모든 테스트 재작성window.open 방법을 사용할 수 있습니다.
    constmockWindowOpen="window.open = function () { };";
    fixture`My App`
        .page`https://devexpress.github.io/testcafe/example/`
        .clientScripts({content:mockWindowOpen});
    test('My test 1',asynct=>{/* ... */});
    test('My test 2',asynct=>{/* ... */});
    
    코드가 거의 변하지 않습니다.TestCafe는 예외를 포착하기 위해 포장만 합니다.

    기타 <head> 스크립트에 오류가 있는지 확인

    <head> 표시에 있기 때문에 스크립트를 주입하면 다른 방식으로 얻을 수 없는 정보를 접근할 수 있습니다.
    한 장면을 고려합니다. <head> 부분에서 다른 스크립트에서 던진 처리되지 않은 이상을 가져와야 합니다.TestCafe API에는 콘솔에서 인쇄된 메시지를 반환하는 방법t.getBrowserConsoleMessages이 포함되어 있습니다.그러나 이 방법은 페이지 코드console.log, console.warnconsole.error 방법으로만 발표될 수 있습니다.t.getBrowserConsoleMessages 방법은 브라우저에서 던진 오류를 가져오지 않습니다.클라이언트 함수를 사용하여 이상을 포착하려고 시도할 수 있지만, 클라이언트 함수는 모든 <head> 스크립트가 완성된 후에 실행됩니다.
    스크립트 주입을 통해 다음 코드를 추가할 수 있습니다.
    각본js
    window.unhandledErrors=[];
    window.onerror=message=>{
        window.unhandledErrors.push(message);
    };
    
    테스트 코드에서 클라이언트 함수를 생성하여 메시지window.unhandledErrors에 액세스할 수 있습니다.
    test('Get Unhandled Errors', async t => {
        consterrors=awaitt.eval(()=>window.unhandledErrors);
        // ...
    }).clientScripts('script.js');
    

    결론


    클라이언트 함수와 스크립트 주입은 TestCafe 기능을 확장하기 때문에 페이지와 직접 상호작용할 수 있습니다.이 기능들은 낮은 단계에서 프로그램을 설정하거나 테스트를 준비하거나 사용자 정의 방식으로 실행에 관한 데이터를 얻을 수 있다.클라이언트 함수와 스크립트를 주입하는 방법을 더 많이 생각해 낼 수 있다.우리는 본고가TestCafe 체계 구조와 예시 사용 장면에 대한 간략한 개술이 이러한 도구에 대한 이해를 향상시키고 더욱 효과적으로 사용할 수 있기를 바랍니다.

    관련 화제

  • Inject Client Scripts
  • Obtain Client-Side Info
  • Select Page Elements
  • 좋은 웹페이지 즐겨찾기