code

유닛 테스트 뷰 - 베스트 프랙티스

starcafe 2023. 4. 3. 21:38
반응형

유닛 테스트 뷰 - 베스트 프랙티스

유닛 테스트 뷰에 대한 경험을 공유할 수 있습니까?뷰에서 유닛 테스트를 수행하는 방법에 대한 튜토리얼을 많이 읽었지만 모든 것에 단점이 있습니다.

저는 다음과 같은 접근법을 취했습니다.효과가 있는데 더 좋은 방법이 없을까 해서요.단점도 몇 가지 있는데 나중에 설명하겠습니다.또, E2E 테스트도 하고 있습니다만, 항상 느리기 때문에, 최소한으로 제한하고 있습니다.

이건 내 컨트롤러야두 개의 변수가 결합되어 있습니다.$scope뷰에서 사용되는 것은 다음과 같습니다.

// test_ctrl.js
angular.module('app', [])
  .controller('TestCtrl', ["$rootScope", "$scope", function ($rootScope, $scope) {
    $scope.bar = "TEST";
    $scope.jobs = [
      {name: "cook"}
    ];
  }]);

뷰는$scope.bar<span>및 그$scope.jobs로 배열하다.ng-repeat지시:

<!-- test.html the view for this controller -->
<span>
  Bar is {{bar || "NOT SET"}}
</span>
<ul>
  <li ng-repeat="job in jobs">{{job.name}}</li>
</ul>

테스트 결과는 다음과 같습니다.

describe('Controller: TestCtrl', function () {
  beforeEach(module('templates'));
  beforeEach(module('app'));

  var TestCtrl, $rootScope, $compile, createController, view, $scope;
  beforeEach(inject(function($controller, $templateCache, _$rootScope_, _$compile_, _$httpBackend_) {
    $rootScope = _$rootScope_;
    $scope = $rootScope.$new();
    $compile = _$compile_;

    createController = function() {
      var html = $templateCache.get('views/test.html');
      TestCtrl = $controller('TestCtrl', { $scope: $scope, $rootScope: $rootScope });
      view = $compile(angular.element(html))($scope);
      $scope.$digest();
    };
  }));

  it('should test the view', function() {
    createController();
    expect(view.find("li").length).toEqual(1)
    console.log($scope.jobs)
  });
});

에서beforeEach기능, 컨트롤러를 설정합니다.createController(테스트 자체에서 호출된) 함수는 이 기능을 통해$templateCache독자적인 컨트롤러가 생성됩니다.$scope그런 다음 템플릿을 컴파일하고,$digest.

템플릿 캐시는 karmas 프리프로세서 ng-html2js로 프리필됩니다.

// karma.conf.js
...
preprocessors: {
  'app/views/*.html': 'ng-html2js'
}
...

이 방법으로는 약간의 문제가 있습니다.또, 몇개의 질문이 있습니다.

1. 오브젝트 내 $$hashKey 키 추가 위치ng-repeat

expect($scope.jobs).toEqual([{name: "cook"}]);에러가 발생합니다.

Expected [ { name : 'cook', $$hashKey : '009' } ] to equal [ { name : 'cook' } ]

나는 그것을 알고 있습니다.ng-repeat이 키를 추가했는데 테스트하기엔 너무 웃겨요.생각할 수 있는 유일한 방법은 컨트롤러 테스트와 뷰 테스트를 분리하는 것입니다.하지만 제가 확인해보니jobs내 컨트롤러의 내부 어레이,$$hashKey존재하지 않습니다.왜 이런 일이 생기는 거죠?

2. 미화 문제

처음 시도했을 때 로컬 스코프만 정의되어 있었습니다.$scope={}가 아니라$scope = $rootScope.$new()다른 컨트롤러 테스트에서도 그랬듯이.단, 로컬 스코프로서의 플레인 오브젝트만으로는 컴파일 할 수 없었습니다($compile(angular.element(html))($scope);에러를 던졌습니다).

그리고 제가 생각하기에 합격을 하는 것이 좋은 방법이라고 생각합니다.$rootScope컨트롤러의 현재 로컬스코프로서 사용됩니다.이게 좋은 방법인가요?아니면 제가 아직 보지 못한 단점이 있나요?

3. 베스트 프랙티스

Angular JS에서 다른 사람들은 어떻게 유닛 테스트를 하고 있는지 알고 싶습니다.시야를 시험해 봐야 할 것 같아요.각도 방향성이 높기 때문에 방수 처리가 되어 있으면 좋겠다고 생각합니다.

저는 당신이 하고 있는 것이 테스트 뷰를 합칠 수 있는 좋은 방법이라고 생각합니다.질문의 코드는 테스트 뷰를 유닛화하려는 사용자에게 좋은 레시피입니다.


1. ng-repeat $$hashKey

데이터는 걱정하지 마세요.대신, 다양한 작업의 결과를 테스트해 보십시오. 왜냐하면 그것이 하루의 끝에 여러분이 정말로 신경 쓰는 것이기 때문입니다.따라서 컨트롤러 생성 후 및 시뮬레이션 후 Jasmine-jquery를 사용하여 DOM 상태를 확인합니다.click()


2. $syslog = $rootScope.$new()는 문제 없습니다.

$rootScope는 Scope의 인스턴스입니다만,$rootScope.$new()ChildScope 인스턴스를 만듭니다.프로덕션에서는 컨트롤러 범위도 ChildScope의 인스턴스이기 때문에 ChildScope 인스턴스를 사용한 테스트가 기술적으로 더 정확합니다.

단, 격리된 스코프를 생성하는 단위 테스트 지시도 마찬가지입니다.언제$compileChildScope 인스턴스가 포함된 지시어는 분리된 범위가 자동으로 생성됩니다(Scope 인스턴스).격리된 스코프에 액세스하려면element.isolateScope()

// decalare these variable here so we have access to them inside our tests
var element, $scope, isolateScope;

beforeEach(inject(function($rootScope, $compile) {
  var html = '<div my-directive></div>';

  // this scope is an instance of ChildScope
  $scope = $rootScope.$new();

  element = angular.element(html);   
  $compile(element)($scope);
  $scope.$digest();

  // this scope is an instance of Scope
  isolateScope = element.isolateScope(); 
}));

3. +1 테스트 뷰

어떤 사람들은 프로젝터로 테스트 뷰를 말한다.프런트 엔드에서 백 엔드로 전체 스택을 테스트하는 경우 프로텍터가 적합합니다.다만, 프로젝터는 느리고, 유닛의 테스트도 빠릅니다.그렇기 때문에 백엔드에 의존하는 어플리케이션의 모든 부분을 조롱함으로써 유닛 테스트로 뷰와 지시를 테스트하는 것이 타당합니다.

디렉티브는 유닛 테스트에 매우 적합합니다.컨트롤러는 그렇지 않습니다.컨트롤러에는 가동 부품이 많아 테스트하기가 더 어려워질 수 있습니다.그래서 저는 디렉티브를 자주 만드는 것에 찬성합니다.그 결과 테스트하기 쉬운 모듈러 코드가 많아졌습니다.

언급URL : https://stackoverflow.com/questions/23083645/unit-test-views-best-practice

반응형