欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

角度测试:开发人员简介

程序员文章站 2022-07-12 13:35:06
...

在本指南中,我们将看看我们如何能够写角5个项目的自动化测试。 角测试是在设置了要么每个项目提供核心功能的角度CLI角快速启动项目

角测试的主题是巨大的,因为它是一个复杂的,非常复杂的话题。 这将需要几个章节或全长度的过程中能充分覆盖。 因此,在本指南中,我会告诉你只是基础知识,让你开始。

先决条件

在写这篇文章的时候,角5.2是当前稳定版本 - 这是我们将在这里使用。 本指南假设您至少有角4+基本面扎实抓好。 它也假设你至少理解这个概念还是有一定的技巧写自动化测试。

我们将立足我们的测试实例角的官方初学者教程演示如何编写组件和服务测试。 你可以找到与我们的测试中完成的代码GitHub的库 在本指南的最后,你应该有能力在5角到实现几个通过的测试。

角度测试:开发人员简介

角测试技术

正如你已经知道,角项目是由模板,组件,服务和模块了。 他们都里面什么被称为角环境中运行。 虽然可以编写孤立的测试,你不会真的知道你的代码将如何与角环境中的其它元素进行交互。

幸运的是,我们有几个技术,可以帮助我们写出这样的单元测试的工作量最少。

1.角测试工具

这是一组搭建角码测试环境需要的类和函数。 你可以找到他们的角的API文档 其中最重要的是测试床 它被用来只是以同样的方式配置角模块作为@NgModule -除了它准备用于测试的模块。 它有一个configureTestingModule功能,你提供所有必要的依赖于您的组件功能在测试环境中。 这里的的一个例子dashboard component正在准备在测试环境中运行。 一些依赖需要通过该组件的测试运行:

 TestBed.configureTestingModule({
  imports: [ RouterTestingModule ],
  declarations: [ DashboardComponent ],
  schemas: [ NO_ERRORS_SCHEMA ],
  providers: [
    {
      provide: HeroService,
      useClass: MockHeroService
    }
  ],
})
.compileComponents();
 

我们将在什么下文进一步这里发生了一个小更仔细。

2.茉莉

茉莉花是编写角测试的事实上的框架。 基本上,它是一个使用行为驱动符号测试框架。 写作茉莉花测试很简单:

 describe('createCustomer' () => {

  it('should create new customer',(customer) => {
    ...
    expect(response).toEqual(newCustomer)
  });

  it('should not create customer with missing fields', () => {
    ...
    expect(response.error.message).toEqual('missing parameters')
  });

  it('should not create customer with existing record', () => {
    ...
    expect(response.error.message).toEqual('record already exists')
  });
});
 

一个茉莉测试的解剖结构是由至少两个部分组成:一个describe功能,这是测试套件,以及it的功能,这是测试本身。 我们通常使用的describe来表示我们关注的功能-例如, createCustomer() 然后,该套件中,我们创建多个it的测试。 每个测试会将目标函数不同的条件下,以确保它的行为与预期。 您可以参考茉莉花文档以获取更多信息。

3.噶

是针对测试代码执行的浏览器环境中源代码的工具。 它支持在它的配置为每个浏览器的测试运行。 结果显示在这两个命令行和浏览器的开发人员来检查哪些测试已经通过或失败。 噶也手表的文件和每当文件更改时可以触发测试重新运行。 在角项目的根,我们有文件karma.conf这是我们用来配置噶。 内容应该是这个样子:

 module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma')
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    coverageIstanbulReporter: {
      reports: [ 'html', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },
    angularCli: {
      environment: 'dev'
    },
    reporters: ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};
 

请检查出因果报应的配置文件 ,以了解如何自定义它。 正如你所看到的,Chrome浏览器被列为用于运行测试的浏览器。 你需要定义一个名为环境变量CHROME_BIN指向你的Chrome浏览器可执行文件的位置。 如果你使用的是Linux,只是这一行添加到您.bashrc文件:

 export CHROME_BIN="/usr/bin/chromium-browser"
 

为了噶运行测试,必须保证与测试文件结束.spec.ts 你应该注意到,噶被设计为主要运行单元测试。 要运行终端到终端的测试,我们需要另一种工具,量角器,我们将看看到明年。

4.量角器

量角器为角的端至端的测试框架。 它运行一个真正的浏览器中你的测试,与它交互和会真正的人。 不同于单元测试,我们测试单个功能,在这里我们测试整个逻辑。 量角器能够填写表单,点击按钮并确认预期的数据和造型显示HTML文件内。 就像噶,量角器有你的角项目的根,自己的配置文件protractor.conf

 const { SpecReporter } = require('jasmine-spec-reporter');

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './e2e/**/*.e2e-spec.ts'
  ],
  capabilities: {
    'browserName': 'chrome'
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },
  onPrepare() {
    require('ts-node').register({
      project: 'e2e/tsconfig.e2e.json'
    });
    jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
  }
};
 

你可以找到它的配置文件在这里 不像茉莉花/噶测试,量角器测试位于外侧src文件夹,一个名为文件夹中的e2e 我们会考虑写终端到终端的测试以后的道路。 现在,让我们开始编写单元测试。

编写单元测试

正如前面提到的,角配备了刚才的一切,你需要编写自动测试为你的项目。 要开始测试,只要运行这个:

 ng test
 

噶会旋转起来,并运行所有可用的测试。 假设你刚刚完成了“英雄之旅”的教程,你应该有这样一个类似的报告:

角度测试:开发人员简介

这些测试得到,当你使用生成的组件,服务和类创建Angular CLI工具。 在创建点,在这些测试的代码是正确的。 然而,当你添加代码到您的组件和服务,测试得到打破。 在下一节中,我们将看到我们如何解决失败的测试。

测试一个组件

单元测试组件可以从两个方面去。 您可以在隔离测试,或者您也可以在转角的环境中进行测试,看看它是如何与它的模板和依赖交互。 硬后者的声音来实现,但采用了棱角分明的测试工具使创建测试更容易。 下面是当您创建使用一个组件,它是为你生成的测试代码的例子Angular CLI工具:

 import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { HeroesComponent } from './heroes.component';

describe('HeroesComponent', () => {
  let component: HeroesComponent;
  let fixture: ComponentFixture<HeroesComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ HeroesComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(HeroesComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
});
 

在第一beforeEach()函数中,我们使用的TestBed.configureTestingModule函数来创建用于测试的组件模块的环境。 它类似于NgModules ,只是在这种情况下,我们要创建一个模块用于测试。
在第二个beforeEach()函数,我们创建的实例component-under-test 一旦我们做到这一点,我们不能配置TestBed再次,作为一个错误将被抛出。

最后,我们必须规范, should be created ,在那里我们确认该component已被初始化。 如果测试通过,这意味着该组件应在角环境中正常运行。 然而,如果失败,很可能部件有一定的相关性,我们还没有包括在测试的配置。 让我们看看我们如何能够处理不同的问题。

测试一个组件使用另一个组件

虽然建设角度的用户界面,我们经常引用其他组件中通过选择一个模板文件。 看看这个例子dashboard.component.html

 <h3>Top Heroes</h3>
...
</div>

<app-hero-search></app-hero-search>
 

在这个例子中,我们引用具有选择另一个组件app-hero-search 如果您尝试运行初始测试的是,它会失败。 这是因为我们还没有宣布在测试环境中引用的组件。 在单元测试中,我们把所有的焦点的组件,我们正在测试。 其他组件是在单元测试我们感兴趣的不是。 我们必须承担他们的工作预期。 包括在我们的测试中引用的组件可能污染的结果。 为了解决这个问题,我们可以嘲笑引用的组件或简单地使用忽略它NO_ERRORS_SCHEMA指令。 下面是一个例子:

 import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';

import { DashboardComponent } from './dashboard.component';

describe('DashboardComponent', () => {
  let component: DashboardComponent;
  let fixture: ComponentFixture<DashboardComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ DashboardComponent ],
      schemas: [ NO_ERRORS_SCHEMA
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(DashboardComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should be created', () => {
    expect(component).toBeTruthy();
  });
});
 

现在,这个试验不应该有分量的依赖关系的问题。 然而,这个测试将无法通过,只是还没有,因为还有另一种情况下,我们必须处理...

测试使用一个元器件的组件

让我们来看看hero-detail.component.html这个时候:

 <div *ngIf="hero">
  <h2>{{ hero.name | uppercase }} Details</h2>
  <div><span>id: </span>{{hero.id}}</div>
  <div>
    <label>name:
      <input [(ngModel)]="hero.name" placeholder="name"/>
    </label>
  </div>
  <button (click)="goBack()">go back</button>
  <button (click)="save()">save</button>
</div>
 

这里我们使用了ngModel指令,它来自FormsModule库。 为了写一个测试支持该模块,我们只需要导入FormsModule ,包括它在TestBed配置:

 import { FormsModule } from '@angular/forms';
...
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ HeroDetailComponent ],
      imports: [ FormsModule],
    })
    .compileComponents();
  }));
  ...
 

这应该修复与问题FormsModule 然而,有一对夫妇更依赖我们需要在我们的测试环境来指定。

测试一个组件,它使用路由模块

让我们来看看hero-detail.component.ts构造函数:

 constructor(
  private route: ActivatedRoute,
  private location: Location,
  private heroService: HeroService   
) {}
 

该组件具有ActivatedRouteLocation ,其处理路由的依赖。 在我们的测试代码, hero-detail.component.spec.ts ,我们可以实现类的模拟版本。 然而,我找到了最好的解决办法是导入RouterTestingModule是这样的:

 import { RouterTestingModule } from ’@angular/router/testing’;
...
beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [ HeroDetailComponent ],
    imports: [ FormsModule, RouterTestingModule ],
  })
  .compileComponents();
}));
 

RoutingTestingModule容易解决了ActivateRouteLocation在我们的测试代码的依赖关系。 RoutingTestingModule也处理存在路由的涉及其他情况。 看看这个代码dashboard.component.html

 <h3>Top Heroes</h3>
<div class="grid grid-pad">
  <a *ngFor="let hero of heroes" class="col-1-4" routerLink="/detail/{{hero.id}}">
    <div class="module hero">
      <h4>{{hero.name}}</h4>
    </div>
  </a>
</div>
 

请注意,我们有一个名为指令routerLink 这是所提供的指令AppRoutingModule库。 如果运行的仪表板测试,它会失败,由于这种依赖性。 为了解决这个问题,只需要实现RoutingTestingModuledashboard.component.spec.ts我们所做的一样hero-detail.component.spec.ts

现在,让我们看看我们如何能够测试依赖于服务组件。

测试一个组件,它使用服务

每个组件需要至少处理逻辑的服务。 有一对夫妇的测试使用的服务组件的方式。 让我们看看message.service.ts ,正在使用的message.component.ts

 import { Injectable } from ’@angular/core’;

@Injectable()
export class MessageService {
  messages: string[] = [];

  add(message: string) {
    this.messages.push(message);
  }

  clear() {
    this.messages = [];
  }
}
 

MessageService有一个非常简单的实现。 它不使用任何外部的依赖。 虽然它的建议,以排除单元测试外部逻辑,我们将在这里破例。 我没有看到复杂我们的测试需要。 出于这个原因,我认为它的最好的,包括在测试的服务。 下面是测试代码message.component.spec.ts

 import { MessageService } from '@services/message.service';
...

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [ MessagesComponent ],
    providers: [ MessageService ]
  })
  .compileComponents();
}))
 

现在,让我们来看看另一个服务, hero-service.ts

 import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
...
@Injectable()
export class HeroService {

  private heroesUrl = 'api/heroes';

  constructor(
    private http: HttpClient,
    private messageService: MessageService) { }

    /** GET heroes from the server */
    getHeroes (): Observable<Hero[]> {
      return this.http.get<Hero[]>(this.heroesUrl)
      .pipe(
         tap(heroes => this.log(`fetched ${heroes.length} heroes`)),
         catchError(this.handleError('getHeroes', []))
       );
    }

    getHero(id: number): Observable<Hero> {
      const url = `${this.heroesUrl}/${id}`;
      return this.http.get<Hero>(url).pipe(
        tap(_ => this.log(`fetched hero id=${id}`)),
        catchError(this.handleError<Hero>(`getHero id=${id}`))
      );
    }
    ...
}
 

所述HeroService类包含相当多的逻辑的-约104线的总额。 它含有多的依赖,其中包括一个到另一个服务。 此外,其所有的功能都是异步的。 这种复杂的代码有污染我们的单元测试的高电位。 出于这个原因,我们应排除其逻辑。 我们通过创建一个模拟版本hero.service.ts 只要创建一个新的文件,并调用它hero.service.mock.ts 嘲笑其功能,使得它的核心逻辑被剥离:

 import { Observable } from 'rxjs/Observable';
import { of } from 'rxjs/observable/of';
import { Hero } from '@models/hero.model';

export class MockHeroService {
  getHeroes(): Observable<Hero[]> {
    return of([]);
  }

  getHero() {
    return of({});
  }
}
 

你可以看到模拟版本多少简单的。 它现在有污染我们的单元测试的非零机会。 把它列入我们的组件规范文件,我们实现它是这样的:

 import { HeroService } from '@services/hero.service';
import { MockHeroService } from '@services/hero.service.mock';
...

  TestBed.configureTestingModule({
      declarations: [ HeroDetailComponent ],
      imports: [ FormsModule, RouterTestingModule ],
      providers: [
        {
          provide: HeroService,
          useClass: MockHeroService
        },
      ],
    })
    .compileComponents();
  }));
...
 

我们使用providers的选择注入MockHeroService作为我们的服务。 实现此使用该服务的所有组件的测试代码。

测试服务

现在我们已经处理了一些在测试组件,让我们看看我们如何能测试服务所出现的常见场景。 服务执行我们的应用程序的核心逻辑,所以这是非常重要的,我们彻底地测试其功能。 正如前面提到的,角测试是一个深刻的主题,所以我们只是要在这里划伤表面。

打开hero.service.ts和检查的职能。 让我强调几点:

 ...
  /** GET heroes from the server */
  getHeroes (): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
       tap(heroes => this.log(`fetched ${heroes.length} heroes`)),
       catchError(this.handleError('getHeroes', []))
     );
  }

  /** UPDATE: update selected hero on the server */
  updateHero (hero: Hero): Observable<any> {
    return this.http.put(this.heroesUrl, hero, httpOptions).pipe(
      tap(_ => this.log(`updated hero id=${hero.id}`)),
      catchError(this.handleError<any>('updateHero'))
    );
  }
...
 

每个功能是由的几行代码,但很多是怎么回事。 为了全面测试每个,我们需要考虑的一些场景。 当我们执行getHeroes()时,服务器可能

  • 送英雄回列表
  • 发送回一个空列表
  • 抛出一个错误
  • 无法响应。

您可以想到的更可能出现的情况,以添加到列表中。 现在,我们已经考虑了可能出现的情况,它的时间来编写测试。 这里有一个如何写一个例子specHeroService

 import { TestBed, inject } from '@angular/core/testing';
import { HttpClientModule, HttpClient, HttpResponse } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { HeroService } from './hero.service';
import { MessageService } from './message.service';
import { Hero } from '@models/hero.model';

const mockData = [
  { id: 1, name: 'Hulk' },
  { id: 2, name: 'Thor'},
  { id: 3, name: 'Iron Man'}
] as Hero[];

describe('HeroService', () => {

  let service;
  let httpTestingController: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule
      ],
      providers: [HeroService, MessageService]
    });
    httpTestingController = TestBed.get(HttpTestingController);
  });

  beforeEach(inject([HeroService], s => {
    service = s;
  }));

  beforeEach(() => {
    this.mockHeroes = [...mockData];
    this.mockHero = this.mockHeroes[0];
    this.mockId = this.mockHero.id;
  });

  const apiUrl = (id: number) => {
    return `${service.heroesUrl}/${this.mockId}`;
  };

  afterEach(() => {
    // After every test, assert that there are no more pending requests.
    httpTestingController.verify();
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  describe('getHeroes', () => {

    it('should return mock heroes', () => {
      service.getHeroes().subscribe(
        heroes => expect(heroes.length).toEqual(this.mockHeroes.length),
        fail
      );
      // Receive GET request
      const req = httpTestingController.expectOne(service.heroesUrl);
      expect(req.request.method).toEqual('GET');
      // Respond with the mock heroes
      req.flush(this.mockHeroes);
    });
  });

  describe('updateHero', () => {

    it('should update hero', () => {
      service.updateHero(this.mockHero).subscribe(
        response => expect(response).toEqual(this.mockHero),
        fail
      );
      // Receive PUT request
      const req = httpTestingController.expectOne(service.heroesUrl);
      expect(req.request.method).toEqual('PUT');
      // Respond with the updated hero
      req.flush(this.mockHero);
    });
  });

  describe('deleteHero', () => {

    it('should delete hero using id', () => {
      const mockUrl = apiUrl(this.mockId);
      service.deleteHero(this.mockId).subscribe(
        response => expect(response).toEqual(this.mockId),
        fail
      );
      // Receive DELETE request
      const req = httpTestingController.expectOne(mockUrl);
      expect(req.request.method).toEqual('DELETE');
      // Respond with the updated hero
      req.flush(this.mockId);
    });

    it('should delete hero using hero object', () => {
      const mockUrl = apiUrl(this.mockHero.id);
      service.deleteHero(this.mockHero).subscribe(
        response => expect(response).toEqual(this.mockHero.id),
        fail
      );
      // Receive DELETE request
      const req = httpTestingController.expectOne(mockUrl);
      expect(req.request.method).toEqual('DELETE');
      // Respond with the updated hero
      req.flush(this.mockHero.id);
    });
  });
});
 

这只是我们应该如何写一个测试的服务,与交互的样品HttpClientModule 检查每个测试,并采取请注意,我们使用HttpTestingController类拦截请求。 在本次测试中,我们控制输入和输出设定不同的场景。 这些测试的主要目的是为了确保我们的服务方法能够很好地处理每一个场景。 请注意,我们还没有完全实现所有必要的测试hero.service.spec.ts ,因为它超出了本指南的范围。

还有更多的话题,我们仍然需要这份指导年底前关注一下。

最终到终端的角度测试

单元测试确保组件和服务在受控测试环境中正常运行。 然而,有没有保证,组件和服务将在角环境中互相交流。 这就是为什么我们需要进行终端到终端的测试。 的端至端的测试是一个模拟人体试验。 换句话说,该测试的目的是与我们的应用程序进行交互,我们做同样的方式 - 通过浏览器界面。

对于我们的英雄应用之旅,还有一些使用情况下,我们可以测试,例如确保 -

  • 5个英雄显示在仪表板组件
  • 所有的英雄都显示在英雄组件
  • 导航链接不破
  • 一个新的英雄可以创建
  • 英雄可以更新
  • 英雄可以被删除。

你可以继续添加到这个列表为更多的功能得到实现。 终端到终端的测试非常有两个部分。

第一部分是一个辅助文件,它提供辅助功能特定的组件。 下面是一个例子app.po.ts

 import { browser, by, element } from 'protractor';

export class AppPage {
  navigateTo() {
    return browser.get('/');
  }

  getParagraphText() {
    return element(by.css('app-root h1')).getText();
  }
}
 

一旦你定义你的助手功能,您可以轻松地访问他们而写的E2E测试。 下面是一个例子e2e/app.e2e.spec.ts

 import { AppPage } from './app.po';

describe('angular-tour-of-heroes App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should display welcome message', () => {
    page.navigateTo();
    expect(page.getParagraphText()).toEqual('Welcome to app!');
  });
});
 

要运行这个测试,只需执行以下命令:

 ng e2e
 

如果这是你执行这个命令在第一时间,您可能需要一个互联网连接。 一旦测试完成后,你很可能得到一个失败的消息,看起来是这样的:

 angular-tour-of-heroes App
   ✗ should display welcome message
     - Expected 'Tour of Heroes' to equal 'Welcome to app!'.
 

让我们来修复错误如下。 我还增加了一个测试只是为了确保我们在指定的重定向app-routing.module.ts作品:

 import { AppPage } from './app.po';
import { browser  } from 'protractor';

describe('angular-tour-of-heroes App', () => {
  let page: AppPage;

  beforeEach(() => {
    page = new AppPage();
  });

  it('should redirect to dashboard', async () => {
    page.navigateTo();
    const url = await browser.getCurrentUrl();
    expect(url).toContain('/dashboard');
  });

  it('should display welcome message', () => {
    page.navigateTo();
    expect(page.getParagraphText()).toEqual('Tour of Heroes');
  });
});
 

再次运行测试。 我们现在应该有通过的测试:

 angular-tour-of-heroes App
  ✓ should redirect to dashboard
  ✓ should display welcome message
 

看着e2e测试运行是一个真棒的感觉。 它给你,你的应用程序将在生产平稳运行的信心。 现在,你有过的味道e2e ,它的时间移动到另一个很酷的测试功能。

代码覆盖

作为一个开发者我们最大的问题是“我们有足够的测试代码?” 幸运的是,我们有一个可以生成“代码覆盖”,以确定如何我们的代码是多少测试的工具。 要生成报告,只需运行以下命令:

 ng test --watch=false --code-coverage
 

覆盖文件夹将在您的角项目的根目录中创建。 浏览文件夹内,你会发现index.html 使用Web浏览器打开它。 您应该看到这样的事情:

角度测试:开发人员简介

我不会去太多细节,但是你可以看到一些类已经过测试,完全而另一些不完全。 由于资源的时间和可用性,它往往并不总是能够实现100%的测试覆盖率。 但是,你可以什么应该是最低的与您的团队决定。 要指定最小,使用karma.conf来配置你这样的代码覆盖率的设置:

 coverageIstanbulReporter: {
  reports: [ 'html', 'lcovonly' ],
  fixWebpackSourcePaths: true,
  thresholds: {
    statements: 80,
    lines: 80,
    branches: 80,
    functions: 80
  }
}
 

上述阈值指定的最小80%的单元测试覆盖。

其他实用程序

现在我们已经覆盖角测试的基础知识。 但是,我们可以通过进入了几步进一步提高我们的代码质量。

1.掉毛

角带有执行代码掉毛的工具。 只需要执行下面的代码做你的项目棉绒检查:

 ng lint
 

此命令会吐出警告有关您的代码 - 例如,当你忘了使用一个分号,或者你用了太多的空间。 该命令也将有助于确定你的语句未使用的代码和某些错误。 经常使用此命令将确保你的团队,每个人都使用一致的风格编写代码。 您可以进一步自定义在皮棉选项tslint.json文件。

2.智能代码编辑器

当涉及到代码编辑器和IDE,我个人最喜欢的是凌动崇高的文本 不过,我最近发现Visual Studio代码 ,里面有更多吸引人的功能。 这是一个可以在Windows,MacOS和Linux操作系统上运行一个免费的代码编辑器。 它借用了很多的Atom,它除了具有额外的功能,我想亮点:

  • 智能感知
  • 错误高亮
  • 现代角扩展

目前,无论是凌动也不崇高文本具备这些功能,当他们建成VSCode。 你只需要安装所需的语言扩展。 为你的智能感知功能列表的选项,你键入的代码。 这就像自动完成,但用的语法正确选项的具体名单。 有了这个功能就很难犯了语法错误。 您还可以看到一个函数的文档,让你看到的返回类型和所需的投入。

角度测试:开发人员简介

Visual Studio代码也有一个适当的错误突出显示功能。 它不仅有语法错误检查,又能保证分配有正确的类型。 例如,如果你试图将数组分配到可观察到的函数的结果,错误将特别为您准备。 VSCode还与角5角兼容扩展。

有了这样的检查你的错误代码,您键入一个IDE是伟大的生产力。 它可以帮助你花更少的时间修正错误,否则你将做出。 可能有其他的代码编辑器,可以实现相同的,但现在我推荐的Visual Studio代码角项目。

3.持续集成

持续集成(CI)是自动化的测试和构建的过程。 作为开发人员,我们经常在孤军奋战了几个星期以上。 当我们更改合并到主分支的时候,有很多错误和冲突的产生。 这可能需要大量的时间来修复。

CI鼓励开发人员编写测试,并在较小的比特经常犯的任务。 CI服务器会自动构建和运行测试,帮助开发人员及早发现错误,从而减少矛盾和问题。 有许多可用于开发角许多CI解决方案。 检查出SitePoint的教程上特拉维斯测试茉莉花和噶

包起来

我们有机会获得万吨左右自动化测试的信息,与测试驱动开发框架一起,帮助我们编写测试。 但是,有几个原因,我们不应该总是写测试:

  1. 不要写一个新的应用测试。 该项目的范围将取决于客户想要什么,或者市场如何响应迅速改变。
  2. 编写测试要求除执行特征更多的时间。 这还需要时间的功能范围的变化,以保持。 如果你的预算低,那么可以跳过编写测试。 与你所拥有的资源的实际。

使叶片当它是正确的时间编写测试的问题。 下面是一些指针:

  1. 你已经完成了原型阶段,你已经牵制了您的应用程序的核心功能。
  2. 你的项目有足够的资金。

现在,假设你决定执行TDD,也有大量的这种好处,应当:

  1. 编写代码,可以测试手段你写的更好质量的代码。
  2. 作为开发人员,你有更多的信心,释放您的最新版本投入生产。
  3. 编写测试代码文档的方式。 这意味着未来的开发人员可以更轻松地升级遗留代码。
  4. 你并不需要雇人进行质量控制,为您的CI服务器将这样做对你的工作。

如果你决定跳过完全适合您的产品准备应用测试,准备面对愤怒和失望的客户在未来。 臭虫的数量将成倍增加,因为在大小代码库的增加。

希望这一直是一个有用的介绍角测试你。 如果您想了解更多,我建议你先坚持到正式角5文档。 大部分的信息在那里是老版本的角度的,除非另有说明。

让我们知道角测试您有任何有趣的提示!

From: https://www.sitepoint.com//angular-testing-introduction/