단위 테스트

코드를 변경하거나 추가한 후에는 기존 단위 테스트를 실행하고 도움이 됩니다. 모든 테스트는 압축되지 않은 버전의 코드에서 실행됩니다.

단위 테스트에는 JS 테스트와 블록 생성기 테스트, 이렇게 두 가지가 있습니다.

JS 테스트

JS 테스트는 Blockly의 핵심입니다. Mocha를 사용하여 단위 테스트를 실행합니다. Sinon으로 종속 항목 스텁 Chai: 코드에 관한 어설션을 만듭니다.

테스트 실행

블록 및 블록 샘플 모두에서 npm run test는 단위 테스트를 실행합니다. Blockly에서는 린팅 및 컴파일과 같은 다른 테스트도 실행합니다. 다음과 같은 작업을 할 수 있습니다. 브라우저에서 tests/mocha/index.html도 열어 모든 Mocha를 대화형으로 실행합니다. 있습니다

테스트 작성

Mocha TDD 인터페이스를 사용하여 테스트를 실행합니다. 테스트는 도구 모음으로 구성되며 추가 하위 도구 모음 및/또는 테스트를 모두 포함할 수 있습니다. 일반적으로 Blockly의 구성요소 (예: toolbox 또는 workspace)에는 자체 테스트 파일이 있습니다. 여기에는 하나 이상의 도구 모음이 포함됩니다. 각 모음에는 해당 모음의 각 테스트 전후에 각각 호출되는 setupteardown 메서드가 있을 수 있습니다.

테스트 도우미

테스트를 작성할 때 유용할 수 있는 Blockly 관련 도우미 함수가 많이 있습니다. 다음 위치에서 확인할 수 있습니다. 핵심blockly-samples

도우미 함수에는 sharedTestSetupsharedTestTeardown가 포함됩니다. 테스트 전후에 호출이 필수입니다 (요구사항 참고). 섹션).

sharedTestSetup:
  • sinon 가짜 타이머를 설정합니다(일부 테스트에서는 this.clock.runAll를 사용해야 함).
  • Blockly.Events.fire 스텁을 사용하여 즉시 실행합니다 (구성 가능).
  • defineBlocksWithJsonArray를 통해 정의된 blockTypes의 자동 정리를 설정합니다.
  • this 컨텍스트에서 액세스 가능: <ph type="x-smartling-placeholder">
      </ph>
    • this.clock(그러나 복원하면 sharedTestTeardown에서 문제가 발생하므로 복원해서는 안 됨)
    • this.eventsFireStub
    • this.sharedCleanup (addMessageToCleanupaddBlockTypeToCleanup) (참고: 다음을 사용하여 블록을 정의한 경우 addBlockTypeToCleanup defineBlocksWithJsonArray)

함수에는 설정을 구성하는 선택적 options 매개변수가 하나 있습니다. 현재 Blockly.Events.fire를 스텁 처리할지 여부를 결정하는 데만 사용됩니다. 즉시 (기본적으로 스텁 처리됨)

sharedTestTeardown:
  • 워크스페이스 this.workspace를 삭제합니다(정의된 위치에 따라 다름, 자세한 내용은 테스트 요구사항 섹션 참고).
  • 모든 스텁을 복원합니다.
  • defineBlocksWithJsonArray를 통해 추가된 모든 블록 유형을 정리합니다. addBlockTypeToCleanup
  • addMessageToCleanup를 통해 추가된 모든 메시지를 정리합니다.

테스트 요구사항

  • 각 테스트는 sharedTestSetup.call(this);를 가장 바깥쪽에 있는 도구 모음을 설정하고 sharedTestTeardown.call(this);를 파일의 가장 바깥쪽에 있는 도구 모음을 해체하는 데 사용됩니다.
  • 일반 도구 상자가 있는 작업공간이 필요한 경우 사전 설정된 도구 상자 테스트 index.html에서 실행되었습니다. 아래에서 예시를 참조하세요.
  • this.workspace를 올바르게 폐기해야 합니다. 대부분의 테스트에서 가장 바깥쪽 도구 모음에서 this.workspace를 정의하여 이후의 모든 도구 모음에 사용합니다. 경우에 따라 내부 도구 모음에서 정의하거나 재정의할 수 있습니다. 예를 들어 테스트 중 하나에 다른 옵션이 있는 작업공간이 필요합니다. 보다 많아야 함). 또한 테스트가 끝나면 폐기해야 합니다.
    • 최외곽 모음에서 this.workspace를 정의하고 다시 정의하지 않으면 추가 조치가 필요하지 않습니다. 자동으로 폐기됩니다. sharedTestTeardown
    • 내부 도구 모음에서 this.workspace를 처음 정의하는 경우 (즉, 가장 바깥쪽 도구 모음에서 정의하지 않은 경우) 수동으로 workspaceTeardown.call(this, this.workspace)를 호출하여 폐기합니다. 해체되는 것 같네요.
    • 가장 바깥쪽 모음에서 this.workpace를 정의한 후 내부 테스트 모음에서 재정의하는 경우 먼저 workspaceTeardown.call(this, this.workspace)를 호출하여 재정의하기 전에 최상위 모음에 정의된 원래 워크스페이스를 해체해야 합니다. 나 또한 이번에도 workspaceTeardown.call(this, this.workspace)을(를) 해체했습니다. 이용할 수 있습니다.

테스트 구조

단위 테스트는 일반적으로 정렬, 실행, 어설션으로 요약할 수 있는 정해진 구조를 따릅니다.

  1. 정렬: 테스트 중인 동작에 필요한 실제 환경의 상태와 조건을 설정합니다.
  2. Act: 테스트 대상 코드를 호출하여 테스트 중인 동작을 트리거합니다.
  3. 어설션: 올바름을 확인하기 위해 반환 값 또는 모의 객체와의 상호작용에 관해 어설션합니다.

간단한 테스트에서는 정렬해야 할 동작이 없을 수도 있고 어설션 단계는 테스트 중인 코드에 대한 호출을 어설션을 만듭니다. 더 복잡한 경우에는 이 세 단계를 따르는 것이 테스트를 더 읽기 쉽게 만듭니다.

다음은 테스트 파일의 예시입니다(실제 파일에서 단순화됨).

suite('Flyout', function() {
  setup(function() {
    sharedTestSetup.call(this);
    this.toolboxXml = document.getElementById('toolbox-simple');
    this.workspace = Blockly.inject('blocklyDiv',
        {
          toolbox: this.toolboxXml
        });
  });

  teardown(function() {
    sharedTestTeardown.call(this);
  });

  suite('simple flyout', function() {
    setup(function() {
      this.flyout = this.workspace.getFlyout();
    });
    test('y is always 0', function() {
      // Act and assert stages combined for simple test case
      chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout is 0');
    });
    test('x is right of workspace if flyout at right', function() {
      // Arrange
      sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
        viewWidth: 100,
      });
      this.flyout.targetWorkspace.toolboxPosition = Blockly.TOOLBOX_AT_RIGHT;
      this.flyout.toolboxPosition_ = Blockly.TOOLBOX_AT_RIGHT;

      // Act
      var x = this.flyout.getX();

      // Assert
      chai.assert.equal(x, 100, 'x is right of workspace');
    });
  });
});

이 예에서 주의할 사항은 다음과 같습니다.

  • 스위트에는 추가 setupteardown 메서드가 있는 다른 스위트가 포함될 수 있습니다.
  • 각 모음 및 테스트에는 설명이 포함된 이름이 있습니다.
  • Chai 어설션은 코드에 관한 어설션을 만드는 데 사용됩니다.
    • 다음 경우에 표시될 문자열 인수(선택사항)를 제공할 수 있습니다. 있습니다 이렇게 하면 손상된 테스트를 더 쉽게 디버그할 수 있습니다.
    • 매개변수의 순서는 chai.assert.equal(actualValue, expectedValue, optionalMessage)입니다. actualexpected를 바꾸는 경우 오류 메시지가 이해되지 않을 것입니다.
  • Sinon은 실제 코드를 호출하고 싶지 않을 때 메서드 스텁을 만드는 데 사용됩니다. 포함 이 예에서는 실제 측정항목 함수를 호출하지 않습니다. 왜냐하면 이 테스트와 관련이 없습니다. Google은 검색 결과가 사용되는 방식에만 관심이 있으며, 테스트 중인 메서드입니다. Sinon은 getMetrics 함수를 스텁하여 테스트 어설션에서 쉽게 확인할 수 있는 미리 준비된 답변입니다.
  • 각 모음의 setup 메서드에는 모든 테스트에 적용되는 일반 설정만 포함되어야 합니다. 특정 동작에 관한 테스트가 특정 조건에 의존하는 경우 해당 조건은 관련 테스트에 명확하게 명시되어야 합니다.

디버깅 테스트

  • 브라우저에서 테스트를 열고 개발자 도구를 사용하여 브레이크포인트를 설정하고 테스트가 예기치 않게 실패하거나 통과하는지 조사할 수 있습니다.
  • 테스트 또는 모음에서 .only() 또는 .skip()를 설정하여 해당 테스트 세트만 실행하거나 테스트를 건너뜁니다. 예를 들면 다음과 같습니다.

    suite.only('Workspace', function () {
      suite('updateToolbox', function () {
        test('test name', function () {
          // ...
        });
        test.skip('test I don’t care about', function () {
          // ...
        });
      });
    });
    

    코드를 커밋하기 전에 이를 삭제해야 합니다.

블록 생성기 테스트

각 블록에는 자체 단위 테스트가 있습니다. 이 테스트는 블록이 제대로 작동하지 않습니다.

  1. Firefox 또는 Safari에서 tests/generators/index.html를 로드합니다. Chrome 및 Opera에는 로컬 'file://' 시스템에서 테스트를 로드하지 못하도록 하는 보안 제한사항이 있습니다(문제 4102447416).
  2. 드롭다운 메뉴에서 테스트할 시스템 관련 부분을 선택합니다. '로드'를 클릭합니다. 블록이 작업공간에 표시됩니다.
  3. 'JavaScript'를 클릭합니다.
    생성된 코드를 복사하여 JavaScript 콘솔에서 실행합니다. 출력이 'OK'로 끝나면 테스트가 통과한 것입니다.
  4. 'Python'을 클릭합니다.
    생성된 코드를 복사하여 Python 인터프리터에서 실행합니다. 출력이 'OK'로 끝나면 테스트에 통과한 것입니다.
  5. 'PHP'를 클릭합니다.
    생성된 코드를 복사하여 PHP 인터프리터에서 실행합니다. 출력이 'OK'로 끝나면 테스트가 통과된 것입니다.
  6. 'Lua'를 클릭합니다.
    생성된 코드를 Lua 인터프리터에서 복사하여 실행합니다. 출력이 'OK'로 끝나면 테스트에 통과한 것입니다.
  7. '다트'를 클릭합니다.
    생성된 코드를 Dart 인터프리터에서 복사하여 실행합니다. 출력이 'OK'로 끝나면 테스트에 통과한 것입니다.

블록 생성기 테스트 편집

  1. 브라우저에 tests/generators/index.html를 로드합니다.
  2. 드롭다운 메뉴에서 시스템의 관련 부분을 선택하고 '로드'를 클릭합니다. 블록이 작업공간에 표시됩니다.
  3. 블록을 변경하거나 추가합니다.
  4. 'XML'을 클릭합니다.
  5. 생성된 XML을 tests/generators/의 적절한 파일에 복사합니다.