Tests tolerantes al cambio en Angular usando SCAMs
Tags: angular, testing, javascript, webdev
Published: 2022-04-09 10:59:00

> Traducción en español del artículo original de Tim Deschryver [Single Component Angular Modules and Component Tests go hand in hand ](https://timdeschryver.dev/blog/single-component-angular-modules-and-component-tests-go-hand-in-hand)publicado el 17 marzo 2022

Escribir buen test no es tan simple como parece, se necesita algo de orientación y práctica para hacerlo bien. Uno de los factores clave que hacen que una buena prueba se destaque es la parte de organización (o configuración).

Para realizar test a los componentes en Angular, hacer módulos de nuestros componentes (Single Component Angular Modules)  _versión corta (SCAMs)_ ayudan a marcar la diferencia entre un test y un buen test.

Utilizando SCAMSs, podemos hacer que nuestros test no sean tan frágiles a los cambios, lo cual hace que el equipo no tenga miedo a cambiar cosas.

Estoy seguro de que un equipo anterior del que formé parte podría haberse beneficiado de los SCAMs y habían tenido menos frustración al hacer cambios en nuestros componentes sin afectar los tests.

La mayoría de los cambios en un componente solo requieren algunos minutos para que un desarrollador experimentado se asegurara de que los tests se pasaran nuevamente. Mientras que un nuevo desarrollador a menudo miraba las pruebas fallidas sin saber qué hacer que ha cambiado o que fallaba el test.

En la mayoría de los casos, esto no tiene sentido porque el componente estaba funcionando, pero después de algunas veces de corregir el test ya estaba más claro, pero no era ideal y era costoso para todos.

SCAMs nos da la respuesta a este problema y en usando junto a [Angular Testing Library](https://testing-library.com/docs/angular-testing-library/intro/) hace súper fácil y divertido hacer pruebas a nuestros componentes.

Miremos un ejemplo ¿Podemos pensar en cambios en el componente MyAwesomeComponent pueden romper renderizado y, por lo tanto, hacen que la prueba falle?

```typescript
it('renders the MyAwesomeComponent component', async () => {
  await render(MyAwesomeComponent, {
    imports: [
      MatButtonModule,
      MatDialogModule,
      MatInputModule,
      MatTableModule,
      MyAwesomeSharedModule,
    ],
    declarations: [MyAwesomeChildComponent, MyAwesomeGrandChildComponent],
    providers: [
      {
        provide: EntityService,
        useValue: mock(EntityService),
      },
    ],
  });

  // ... Lo que sigue del test esta aqui ...
});
```

Puedes pensar varias razones por la cual el test falla, algunas serian por ejemplo:

- Un nuevo módulo se utiliza en el componente MyAwesomeComponent
- MyAwesome component está utilizando un nuevo componente hijo.
- Quizás un componente hijo de nuestro MyAwesomeComponet está usando un nuevo componente.
- Un componente fue eliminado.
- MyAwsomeComponent lo han agregado en MyAwesomeShareModule 

¿Muchas opciones no? 

## MODULARIZAR LOS COMPONENTS.

Para hacer que nuestros tests sean más tolerantes a los cambios y no tan frágiles, nosotros podemos utilizar SCAMs, con los SCAMs los cambios de nuestros componentes o directivas están encapsulados con su módulo. 

Como el módulo es importando en el test, la configuración se actualiza de forma automática.

Sin meternos en más detalles sobre SCAM, un componente modula rizado se verá de la siguiente manera:

> Si quieres leer mas sobre [Single Component Angular Modules SCAMs](https://dev.to/this-is-angular/emulating-tree-shakable-components-using-single-component-angular-modules-13do) (en ingles) por [Lars Gyrup Brink Nielsen](@layzee)

```typescript
@NgModule({
  declarations: [MyAwesomeComponent],
  exports: [MyAwesomeComponent],
  imports: [
    MatButtonModule,
    MatDialogModule,
    MatInputModule,
    MatTableModule,
    MyAwesomeSharedModule,
    MyAwesomeChildComponentModule,
    MyAwesomeGrandChildComponentModule,
  ],
})
export class MyAwesomeComponentModule {}
```

## IMPORTANDO EL MÓDULO

Para hacer nuestro test utilizamos la función render de testing library e importamos el módulo. Para evitar que el componente se agregue de manera automáticamente a las declaraciones de TestBed, utilizamos la propiedad excludeComponentDeclaration.

```typescript
it('renders the MyAwesomeComponent component', async () => {
    await render(MyAwesomeComponent, {
        excludeComponentDeclaration: true,
        imports: [MyAwesomeComponentModule],
        providers: [
            {
                provide: EntityService,
                useValue: mock(EntityService),
            },
        ],
    });

    // ... lo que continua del test esta aqui...
});
```

## CONFIGURANDO POR DEFECTO
Cuando nuestro equipo use SCAM por defecto, la propiedad excludeComponentDeclaration se puede configurar globalmente mediante el método configure en test.ts.

```typescript
import { configure } from '@testing-library/angular';

configure({
    excludeComponentDeclaration: true,
});
```

Nuestro test se verá de esta manera

```typescript
t('renders the MyAwesomeComponent component', async () => {
    await render(MyAwesomeComponent, {
        imports: [MyAwesomeComponentModule],
        providers: [
            {
                provide: EntityService,
                useValue: mock(EntityService),
            },
        ],
    });

});
```

## SIMPLIFICANDO EL TEST

También puede utilizar el template, en lugar del el tipo representar el componente. Esto no requiere asignemos la  propiedad excludeComponentDeclaration.

```typescript
t('renders the MyAwesomeComponent component', async () => {
    await render(`<my-awesome-component></my-awesome-component>`, {
        imports: [MyAwesomeComponentModule],
        providers: [
            {
                provide: EntityService,
                useValue: mock(EntityService),
            },
        ],
    });

});
```

## CONCLUSIÓN
Si bien las SCAM tienen muchas características positivas, los beneficios que brindan a los test de componentes unas de mis favoritas. Desde mi experiencia, ha sido un placer y me siento más productivo que antes.

Al organizar los componentes básicos en SCAM, nuestros tests no necesita averiguar qué dependencias se requiere o tener que los test. Con SCAM, cada cambio en el código de del componente se refleja directamente en nuestros tests.

Si sigue esta práctica, nuestros tests se vuelven resistentes a los cambios internos y concentrarnos por completo en las nuevas funciones. 

> OPINION PERSONAL

Utilizar SCAMs nos quita muchos dolores de cabeza y el miedo de romper los tests, a la más mínima de cambios, ya que es muy frustrante, puesto que cada cambio de nuestro código se refleja en el test y genera doble trabajo.

Espero que esto les ayuda a escribir tests más tolerantes al cambio.

Photo by <a href="https://unsplash.com/@grimstad?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Håkon Grimstad</a> on <a href="https://unsplash.com/s/photos/changes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>