첫 번째 AngularJS 앱 튜토리얼 파트 2: 스캐폴딩, 빌드 및 테스트를 위한 도구

게시 됨: 2022-03-11

소개

AngularJS 응용 프로그램 개발을 지원하는 데 사용할 수 있는 많은 도구를 통해 많은 사람들은 AngularJS가 매우 복잡한 프레임워크라는 인상을 받지만 전혀 그렇지 않습니다. 이것이 제가 이 튜토리얼 시리즈를 시작한 주된 이유 중 하나입니다.

1부에서는 AngularJS 프레임워크의 기본 사항을 다루었고 첫 번째 애플리케이션을 작성하는 것으로 시작했습니다. 이 포스트는 초보자를 위해 작성되었습니다. 경험이 많은 AngularJS 개발자라면 성장하는 스타트업에서 사용 중인 AngularJS에 대한 설명이나 지시문을 이해하는 데 더 관심이 있을 수 있습니다.

이 튜토리얼에서는 애플리케이션 로직 레이어를 따로 설정하고 스캐폴딩, 종속성 관리 및 테스트 준비(단위 및 종단 간 모두)를 포함하여 적절한 AngularJS 프로젝트 설정을 수행하는 방법을 배웁니다. Yeoman, Grunt 및 Bower와 같은 AngularJS 도구를 사용하여 이 작업을 수행합니다. 그런 다음 Karma를 사용하여 Jasmine 테스트를 작성하고 실행하는 프로세스를 검토합니다.

Karma, Jasmine, Grunt, Bower, Yeoman... 이 모든 도구는 무엇입니까?

AngularJS를 스캐폴딩하고, AngularJS를 테스트하고, 앱을 적절하게 빌드하는 데 도움이 되는 개발 도구가 너무 많습니다.

JavaScript로 작업하는 경우 Angular를 처음 접하더라도 이러한 도구 중 적어도 일부는 이미 알고 있을 가능성이 매우 높습니다. 그러나 공통 기준선을 보장하기 위해 어떤 가정도 하지 않겠습니다. 이러한 각 기술과 유용한 용도를 간략하게 살펴보겠습니다.

  • Karma(이전에는 Testacular로 알려짐)는 Google의 JavaScript 테스트 실행기이며 AngularJS를 테스트하기 위한 자연스러운 선택입니다. 실제 브라우저(전화/태블릿 브라우저 포함)에서 테스트를 실행할 수 있을 뿐만 아니라 테스트 프레임워크에 구애받지 않습니다. 즉, 선택한 테스트 프레임워크(예: Jasmine, Mocha 또는 QUnit 등)와 함께 사용할 수 있습니다.

  • Jasmine은 적어도 이 포스트에서 우리가 선택한 테스트 프레임워크가 될 것입니다. 그것으로 작업한 적이 있다면 그것의 구문은 RSpec의 그것과 매우 유사합니다. (없더라도 걱정하지 마십시오. 이 자습서의 뒷부분에서 더 자세히 확인할 것입니다.)

  • Grunt는 축소, 컴파일(또는 빌드), 테스트 및 AngularJS 애플리케이션의 미리보기 설정과 같은 여러 반복 작업을 자동화하는 데 도움이 되는 작업 실행기입니다.

  • Bower는 CSS 프레임워크, JavaScript 라이브러리 등과 같은 모든 애플리케이션 종속성을 찾고 설치하는 데 도움이 되는 패키지 관리자입니다. Rails 번들러와 마찬가지로 git을 통해 실행되며 종속성을 수동으로 다운로드하고 업데이트할 필요가 없습니다.

  • Yeoman은 Grunt, Bower 및 스캐폴딩 도구 Yo의 3가지 핵심 구성요소를 포함하는 도구 세트입니다. Yo는 생성기(단지 스캐폴딩 템플릿임)를 사용하여 상용구 코드를 생성하고 프로젝트에 대해 Grunt 및 Bower를 자동으로 구성합니다. 거의 모든 JavaScript 프레임워크(Angular, Backbone, Ember 등)에 대한 생성기를 찾을 수 있지만 여기서는 Angular에 중점을 두고 있으므로 Generator-Angular 프로젝트를 사용할 것입니다.

그럼 어디서부터 시작할까요?

자, 가장 먼저 해야 할 일은 필요한 도구를 설치하는 것입니다.

git, node.js, npm이 아직 설치되어 있지 않다면 계속해서 설치하세요.

그런 다음 명령줄로 이동하여 다음 명령을 실행하여 Yeoman 도구를 설치합니다.

 npm install -g yo grunt-cli bower

아, 그리고 잊지 마세요. 우리는 AngularJS 생성기를 사용할 것이므로 당신도 설치해야 합니다:

 npm install -g generator-angular

자, 이제 준비가 되었습니다...

AngularJS 애플리케이션 스캐폴드/생성

지난 시간에 Angular-seed 프로젝트에서 상용구 코드를 수동으로 차용했습니다. 이번에는 (제너레이터-앵글과 함께) yo가 우리를 위해 그렇게 하도록 할 것입니다.

우리가 해야 할 일은 새 프로젝트 폴더를 만들고 탐색하고 다음을 실행하는 것입니다.

 yo angular

Bootstrap 및 Compass를 포함할지 여부와 같은 몇 가지 옵션이 제공됩니다. 지금은 나침반에 아니오 , 부트스트랩에 라고 합시다. 그런 다음 포함할 모듈(리소스, 쿠키, 삭제 및 라우팅)에 대한 메시지가 표시되면 angular-route.js 만 선택합니다.

이제 프로젝트 스캐폴드가 생성되고(1분 정도 소요될 수 있음) Karma와 통합되고 모두 사전 구성됩니다.

참고: 여기에서 모듈을 이 튜토리얼의 1부에서 구축한 애플리케이션에서 사용한 것으로 제한한다는 점을 명심하십시오. 자신의 프로젝트에 대해 이 작업을 수행할 때 포함해야 하는 모듈을 결정하는 것은 사용자의 몫입니다.

이제 Jasmine을 사용할 것이므로 karma-jasmine 어댑터를 프로젝트에 추가해 보겠습니다.

 npm install karma-jasmine --save-dev

Chrome 인스턴스에서 테스트를 실행하려는 경우 karma-chrome-launcher 도 추가해 보겠습니다.

 npm install karma-chrome-launcher --save-dev

자, 모든 것을 제대로 했다면 이제 프로젝트 파일 트리가 다음과 같이 보일 것입니다.

이러한 AngularJS 도구를 사용하는 샘플 프로젝트 파일 트리는 다음과 같습니다.

정적 애플리케이션 코드는 app/ 디렉토리로 이동하고 test/ 디렉토리에는 테스트가 포함될 것입니다. 루트에 있는 파일은 프로젝트 구성 파일입니다. 각각에 대해 배울 것이 많지만 지금은 기본 구성을 그대로 사용하겠습니다. 따라서 다음 명령으로 간단히 수행할 수 있는 앱을 처음으로 실행해 보겠습니다.

 grunt serve

그리고 짜잔! 이제 앱이 우리 앞에 팝업되어야 합니다!

AngularJS용 Bower에 대해 조금

정말 중요한 부분(즉, 테스트)으로 들어가기 전에 Bower에 대해 조금 더 알아보기 위해 잠시 시간을 내어 보겠습니다. 앞서 언급했듯이 Bower는 패키지 관리자입니다. 우리 프로젝트에 lib 또는 플러그인을 추가하는 것은 bower install 명령을 사용하여 간단히 수행할 수 있습니다. 예를 들어, modernizr 을 포함하려면 다음 작업만 수행하면 됩니다(물론 프로젝트 디렉토리 내에서).

 bower install modernizr

그러나 이것이 Modernizr를 우리 프로젝트의 일부로 만드는 동안( app/bower_components modernizr 에 위치할 것입니다), 우리는 여전히 우리가 필요에 따라 이를 우리의 애플리케이션에 포함(또는 포함되어야 하는 시기를 관리)할 책임이 있습니다. 수동으로 추가한 lib와 관련이 있습니다. 이를 수행하는 한 가지 방법은 다음 <script> 태그를 index.html 에 추가하는 것입니다.

 <script src="bower_components/modernizr/modernizr.js"></script>

또는 bower.json 파일을 사용하여 종속성을 관리할 수 있습니다. 지금까지 모든 단계를 주의 깊게 수행한 후 bower.json 파일은 다음과 같아야 합니다.

 { "name": "F1FeederApp", "version": "0.0.0", "dependencies": { "angular": "1.2.15", "json3": "~3.2.6", "es5-shim": "~2.1.0", "jquery": "~1.11.0", "bootstrap": "~3.0.3", "angular-route": "1.2.15" }, "devDependencies": { "angular-mocks": "1.2.15", "angular-scenario": "1.2.15" } }

구문은 꽤 자명하지만 여기에서 더 많은 정보를 얻을 수 있습니다.

그런 다음 원하는 추가 새 종속성을 추가할 수 있으며 필요한 것은 다음 명령으로 설치하기만 하면 됩니다.

 bower install

이제 몇 가지 테스트를 작성해 봅시다!

자, 이제 1부에서 중단한 부분을 실제로 선택하고 AngularJS 앱에 대한 몇 가지 테스트를 작성할 시간입니다.

그러나 먼저 우리가 해결해야 할 약간의 문제가 있습니다. generator-angular의 개발자는 angular-seed 프로젝트(공식 Angular 상용구)를 기반으로 프로젝트 템플릿을 기반으로 했지만 어떤 이유에서인지 잘 이해가 되지 않는데 그들은 다음과 같이 결정했습니다. app 폴더 명명 규칙을 변경합니다( cssstyles 로, jsscripts 로 변경 등).

결과적으로 우리가 원래 작성한 앱에는 이제 방금 생성한 스캐폴드와 일치하지 않는 경로가 있습니다. 이 문제를 해결하기 위해 여기에서 앱 코드를 다운로드하고 이 시점부터 해당 버전으로 작업해 보겠습니다(대부분 우리가 원래 작성한 것과 똑같은 앱이지만 생성기 각도 이름 지정과 일치하도록 경로가 업데이트됨).

앱을 다운로드한 후 tests/spec/controllers 폴더로 이동하여 다음을 포함하는 drivers.js 라는 파일을 만듭니다.

 describe('Controller: driversController', function () { // First, we load the app's module beforeEach(module('F1FeederApp')); // Then we create some variables we're going to use var driversController, scope; beforeEach(inject(function ($controller, $rootScope, $httpBackend) { // Here, we create a mock scope variable, to replace the actual $scope variable // the controller would take as parameter scope = $rootScope.$new(); // Then we create an $httpBackend instance. I'll talk about it below. httpMock = $httpBackend; // Here, we set the httpBackend standard reponse to the URL the controller is // supposed to retrieve from the API httpMock.expectJSONP( "http://ergast.com/api/f1/2013/driverStandings.json?callback=JSON_CALLBACK").respond( {"MRData": {"StandingsTable": {"StandingsLists" : [{"DriverStandings":[ { "Driver": { "givenName": 'Sebastian', "familyName": 'Vettel' }, "points": "397", "nationality": "German", "Constructors": [ {"name": "Red Bull"} ] }, { "Driver": { "givenName": 'Fernando', "familyName": 'Alonso' }, "points": "242", "nationality": "Spanish", "Constructors": [ {"name": "Ferrari"} ] }, { "Driver": { "givenName": 'Mark', "familyName": 'Webber' }, "points": "199", "nationality": "Australian", "Constructors": [ {"name": "Red Bull"} ] } ]}]}}} ); // Here, we actually initialize our controller, passing our new mock scope as parameter driversController = $controller('driversController', { $scope: scope }); // Then we flush the httpBackend to resolve the fake http call httpMock.flush(); })); // Now, for the actual test, let's check if the driversList is actually retrieving // the mock driver array it('should return a list with three drivers', function () { expect(scope.driversList.length).toBe(3); }); // Let's also make a second test checking if the drivers attributes match against // the expected values it('should retrieve the family names of the drivers', function () { expect(scope.driversList[0].Driver.familyName).toBe("Vettel"); expect(scope.driversList[1].Driver.familyName).toBe("Alonso"); expect(scope.driversList[2].Driver.familyName).toBe("Webber"); }); });

이것은 우리의 driverscontroller 에 대한 테스트 모음입니다. 많은 코드처럼 보일 수 있지만 대부분은 실제로는 모의 데이터 선언일 뿐입니다. 정말 중요한 요소를 간단히 살펴보겠습니다.

  • describe() 메서드는 테스트 스위트를 정의합니다.
  • it() 은 적절한 테스트 사양입니다.
  • 모든 beforeEach() 함수는 각 테스트 직전에 실행됩니다.

여기서 가장 중요한(그리고 잠재적으로 혼란스러운) 요소는 httpMock 변수에 대해 인스턴스화한 $httpBackend 서비스입니다. 이 서비스는 실제 서버가 프로덕션 환경에서 하는 것처럼 가짜 백엔드 역할을 하고 테스트 실행 시 API 호출에 응답합니다. 이 경우, expectJSONP() 함수를 사용하여 주어진 URL(서버에서 정보를 가져오는 데 사용하는 것과 동일한 URL)에 대한 JSONP 요청을 가로채도록 설정하고 대신 세 드라이버가 포함된 정적 목록을 반환합니다. 실제 서버 응답. 이를 통해 컨트롤러에서 반환되어야 하는 내용을 확실히 알 수 있습니다. 따라서 expect() 함수를 사용하여 결과를 예상한 결과와 비교할 수 있습니다. 일치하면 테스트가 통과됩니다.

테스트 실행은 다음 명령으로 간단히 수행됩니다.

 grunt test

드라이버 세부 정보 컨트롤러( drivercontroller )에 대한 테스트 제품군은 방금 본 것과 상당히 유사해야 합니다. 나는 당신이 그것을 연습으로 스스로 알아내려고 노력하는 것이 좋습니다(또는 당신이 할 수 없다면 여기를 살펴볼 수 있습니다).

종단 간 AngularJS 테스트는 어떻습니까?

Angular 팀은 최근 Protractor라는 종단 간 테스트를 위한 새로운 러너를 도입했습니다. 웹드라이버를 사용하여 브라우저에서 실행되는 응용 프로그램과 상호 작용하고 기본적으로 Jasmine 테스트 프레임워크도 사용하므로 구문이 단위 테스트의 구문과 매우 일치합니다.

그러나 Protractor는 상당히 새로운 도구이기 때문에 Yeoman 스택과의 통합 및 generator-angular 는 여전히 상당한 양의 구성 작업이 필요합니다. 이를 염두에 두고 이 튜토리얼을 가능한 한 간단하게 유지하려는 의도는 AngularJS의 종단 간 테스트를 심층적으로 다루기 위해 독점적으로 미래 게시물을 할애하는 것입니다.

결론

튜토리얼 시리즈의 이 시점에서 우리는 yo 를 사용하여 Angular 앱을 스캐폴딩하고, bower 로 종속성을 관리하고, karmaprotractor 를 사용하여 일부 테스트를 작성/실행하는 방법을 배웠습니다. 그러나 이 튜토리얼은 이러한 AngularJS 도구 및 사례에 대한 소개로만 사용된다는 점을 명심하십시오. 우리는 여기에서 그들 중 어느 것도 깊이 분석하지 않았습니다.

우리의 목표는 단순히 당신이 이 길을 시작할 수 있도록 돕는 것이었습니다. 여기에서 이 놀라운 프레임워크와 도구 모음에 대해 배울 수 있는 모든 것을 배우는 것은 사용자의 몫입니다.

부록: 저자의 일부 (중요한) 메모

이 튜토리얼을 읽은 후 어떤 사람들은 “잠깐만요. 실제로 앱 코딩을 시작하기 전에 이 모든 작업을 수행해야 하지 않습니까? 이것은 이 튜토리얼의 일부가 아니어야 합니까?”

그것에 대한 나의 짧은 대답은 아니오 입니다. 1부에서 보았듯이 실제로 첫 번째 Angular 앱을 코딩하기 위해 이 모든 것을 알 필요는 없습니다. 오히려 이 게시물에서 논의한 대부분의 도구는 개발 워크플로를 최적화하고 TDD(테스트 주도 개발)를 연습하는 데 도움이 되도록 설계되었습니다.

그리고 TDD에 대해 말하면 TDD의 가장 기본적인 개념은 확실히 건전한 개념입니다. 즉, 코드를 작성하기 전에 테스트를 작성하십시오. 그러나 어떤 사람들은 그 개념을 너무 멀리 가져갑니다. TDD는 학습 방법이 아니라 개발 방식입니다. 따라서 코드를 작성 하기 전에 테스트를 작성하는 것은 많은 의미가 있는 반면, 코딩 방법을 배우기 전에 테스트를 작성 하는 방법 을 배우는 것은 그렇지 않습니다.

저는 개인적으로 이것이 공식 Angular 튜토리얼이 너무 복잡하게 느껴질 수 있고 이전 프론트 엔드 MVC/TDD 경험이 없는 사람들이 따르기가 거의 불가능할 수 있는 주된 이유라고 생각합니다. 이것이 제가 이 튜토리얼 시리즈를 시작한 주된 이유 중 하나입니다.

AngularJS 세계를 탐색하는 방법을 배우는 사람들을 위한 제 개인적인 조언은 다음과 같습니다. 자신에게 너무 무리하지 마십시오. 한 번에 모든 것을 배울 필요는 없습니다(사람들이 다르게 말하더라도!). 다른 프론트엔드/테스트 프레임워크에 대한 이전 경험에 따라 AngularJS는 처음에 이해하기 꽤 어려울 수 있습니다. 따라서 자신만의 간단한 앱을 작성할 수 있을 때까지 배워야 할 모든 것을 배우고, 프레임워크의 기본에 익숙해지면 가장 잘 작동하는 장기 개발 사례를 선택하고 적용하는 데 관심을 가질 수 있습니다. 너.

물론, 그것은 내 겸손한 의견이며 모든 사람이 그 접근 방식에 동의하지는 않을 것입니다(그리고 Angular 개발 팀은 내가 이것을 게시하면 나를 고용한 킬러를 보낼 수도 있습니다). 그러나 그것이 제 비전이고 많은 사람들이 그렇게 할 것이라고 확신합니다. 저와 동의할 사람이 있습니다.

관련 항목: Angular 6 자습서: 새로운 기능의 새로운 기능