Durante la próxima revisión de una solicitud de extracción densa, me encontré con pruebas unitarias con nombres incorrectos de casos de prueba. La discusión de la redacción en los casos de prueba resultó ser similar a la conversación entre Yanychar y Legkostupov en la película "72 metros" ("si fuera tan inteligible en la escuela ..."). La conversación dio la idea de que en los recursos en idioma ruso es difícil encontrar una guía explicativa precisamente por palabras textuales. Decidí buscarme en ruso (generalmente uso solo fuentes de habla inglesa). En un habr encontré varios manuales sobre pruebas unitarias, pero todos ellos omiten detalles de formulaciones en casos de prueba. Debajo del corte, mi intento de llenar este vacío.
Descargo de responsabilidad
Existe la posibilidad de que estuviera mirando mal / leyendo demasiado en diagonal. Aquí hay un ejemplo de cómo se cubre el tema de este artículo en aquellos artículos que me llamaron la atención.

TDD para principiantes
A solicitud de colegas, que no se sienten cómodos leyendo manuales en inglés, decidí traducir y compilar manuales en inglés.
Del traductor
Tomé estos dos materiales como base para el artículo:
También tengo que señalar que en algunos ejemplos de prueba tuve que hacer una traducción parcial al ruso. La redacción en los bloques "describir" intencionalmente permanece en inglés, como con alta probabilidad contendrán el nombre de funciones, módulos JS u otras entidades en el código, pero en los bloques "it" el texto ya está traducido para facilitar su lectura.
Mi preferencia personal es que todo en el código debe estar en inglés.
Pruebas de nomenclatura
El nombre de la prueba debe describir su propósito de la manera más breve y explícita posible. El nombre y la descripción de la prueba es lo primero que debe indicar la causa del mal funcionamiento. El resultado de la prueba en la consola debe leerse correctamente en términos de gramática. Los desarrolladores de terceros no deben resolver acertijos en sus cabezas, tratando de adivinar en qué estaba pensando el autor de la prueba. Las pruebas son parte de la documentación del programa y también deben escribirse correctamente.
MAL ejemplo:
describe('discoveryService => initDiscoveries', () => { it(' discoveries ( , ..)', () => {
A partir de los ejemplos anteriores, es difícil entender qué acción (es) específica (s) se está realizando y qué resultado concreto debe conducir la acción.
BUEN ejemplo:
describe('discoveryService => initDiscoveries', () => { it(' discoveries', () => {
Nota perev. # 1: tenga en cuenta que el bloque de texto en él comienza con mayúscula, como Es una continuación de la oración que comenzó en descibe .
Nota perev. # 2: en los ejemplos anteriores, "discoveryService => initDiscoveries" se divide más correctamente en dos bloques descibe (uno está anidado en el otro).
Nota perev. # 3: tenga en cuenta que en los ejemplos sobre descubrimiento anteriores no hay una segunda parte de la descripción del caso de prueba; implica un texto de la forma "sobre su invocación", que no es muy bueno desde el punto de vista de la manifestación; en casos simples, copiar y pegar "cuando se llama" no es particularmente rentable, en mi humilde opinión.
En el bloque de descripción, generalmente se coloca una descripción del trabajo elemental (Unidad de trabajo, UoW). La redacción en el bloque it debe continuar con el patrón " unidad de trabajo - escenario / contexto - comportamiento esperado " que comenzó en describir:
[ ] [ / ] ( | ) [ ]
o como un código:
describe('[unit of work]', () => { it(' [ ] / [/]', () => { }); });
Si varios grupos de prueba siguen el mismo guión o se ajustan al mismo contexto, puede usar los bloques anidados descritos .
describe('[unit of work]', () => { describe('// [scenario/context]', () => { it('/ [expected behaviour]', () => { }); }); }); describe(' Gallery', () => { describe(' ', () => { it(' ', () => { }); it(' ', () => { }); });
UNA PRUEBA - UN PROBLEMA
Cada prueba debe centrarse en un escenario específico en la aplicación. La prueba, responsable de un aspecto específico, puede identificar la causa específica del mal funcionamiento. Cuanto más específica sea la prueba, menos probable es que haya varias razones para el comportamiento incorrecto. Intente colocar solo un bloque esperado en un bloque.
MAL ejemplo:
describe('isUndefined function', ()=> { it(' true or false undefined', () => { expect(isUndefined(undefined)).toEqual(true); expect(isUndefined(true)).toEqual(false); }); });
El bloque it contiene dos bloques de espera . Esto significa que el desarrollador, al ver un resultado negativo de esta prueba, no podrá determinar exactamente qué es incorrecto en su código y cómo solucionarlo.
BUEN ejemplo:
describe('isUndefined function', ()=> { it(' true, undefined', () => { expect(isUndefined(undefined)).toEqual(true); }); it(' false ', () => { expect(isUndefined(true)).toEqual(false); }); });
Cada prueba en el ejemplo anterior evalúa un problema específico. Además, la descripción de la prueba describe claramente en qué caso se aprobará. En ambos casos en la consola, el desarrollador leerá una lista de los resultados que se esperan bajo qué acciones / condiciones de la funcionalidad del usuario probado.
Prueba de comportamiento
Mire la imagen, no mire los trazos. Pruebe el script / comportamiento personalizado, no los detalles de implementación. Luego, cambiar los detalles de implementación no afectará los resultados de la prueba. Un resultado negativo de la prueba debe indicar si el programa se comporta correctamente desde el punto de vista del usuario. La prueba no debe controlar / limitar los detalles de implementación.
MAL ejemplo:
it(' discovery ', () => { discoveriesCache.addDiscovery('57463', 'John'); expect(discoveriesCache._discoveries[0].id).toBe('57463'); expect(discoveriesCache._discoveries[0].name).toBe('John'); });
¿Qué hay de malo aquí? En primer lugar, dos esperan bloques, pero esto no es lo principal. En segundo lugar, no se prueba el comportamiento, sino los detalles de implementación. Los detalles de implementación cambiarán (se renombrarán los campos privados): la prueba dejará de ser válida y deberá reescribirse.
BUEN ejemplo:
it(' discovery ', () => { discoveriesCache.addDiscovery('57463', 'John'); expect(discoveriesCache.isDiscoveryExist('57463', 'John')).toBe(true); });
Este ejemplo prueba una API pública que debería ser lo más estable posible.
CONCLUSIÓN DE UN TRADUCTOR
"Onegin fue un pedante ..." Tengo la impresión de que la mayoría de los desarrolladores prestan poca atención a la precisión y legibilidad de los nombres de prueba. A menudo observo discusiones bastante largas como "¿Qué hace este código?" O "Por qué este código". Esto se aplica tanto al código principal en JS (nombres confusos y confusos de módulos, servicios, funciones y variables) como a pruebas (casos borrosos, detalles de implementación de pruebas, descripciones difusas). Todo esto lleva al hecho de que el código no cumple exactamente lo que se espera.
En una de sus entrevistas, David Heinemeier Hansson (creador del marco Rails) dijo algo como lo siguiente:
"Las pruebas unitarias solo muestran que su programa está haciendo lo esperado%: o".
Se refería a que el comportamiento debería ser probado, no codificar unidades. Y el lenguaje textual debe tener un patrón de comportamiento. Es decir "La entidad A debe comportarse de tal y tal manera bajo tales condiciones". Una cadena de la forma describir [- describir ] - it - esperar debe convertirse en una formulación tan plegable.
Gracias por su atencion!