Esta es una guía completa para proporcionar confiabilidad en JavaScript y Node.js. Aquí se recopilan docenas de las mejores publicaciones, libros y herramientas.
Primero, trate con los métodos de prueba generalmente aceptados que subyacen a cualquier aplicación. Y luego puede profundizar en el área de interés para usted: interfaz e interfaces, backend, CI o todo lo anterior.
Contenido
Sección 0. Regla de oro
0. Regla de oro: apegarse a las pruebas Lean
Que hacer El código de prueba es diferente de lo que entra en funcionamiento. Hazlo lo más simple posible, corto, libre de abstracciones, soltero, maravilloso en el trabajo y económico. Otra persona debe mirar la prueba e inmediatamente comprender lo que está haciendo.
Nuestros jefes están ocupados con el código de producción, no tienen espacio libre para una complejidad adicional. Si introducimos una nueva porción de código complejo en nuestra pobre mente, esto ralentizará el trabajo de todo el equipo en la tarea, por lo que estamos probando. De hecho, debido a esto, muchos equipos simplemente evitan las pruebas.
Pruebas: esta es una oportunidad para obtener un asistente amable y sonriente, con quien es muy bueno trabajar y que ofrece un gran retorno de las pequeñas inversiones. Los científicos creen que en nuestro cerebro hay dos sistemas: uno para acciones que no requieren esfuerzo, como conducir en una carretera vacía, y el segundo para operaciones complejas que requieren conciencia, como resolver ecuaciones matemáticas. Cree sus pruebas para el primer sistema, de modo que cuando mire el código tenga una sensación de simplicidad comparable a la edición de un documento HTML, y no con una solución
2X(17 × 24)
.
Esto se puede lograr mediante una cuidadosa selección de métodos, herramientas y objetivos para las pruebas, de modo que sean económicos y den un gran retorno de la inversión. Pruebe solo tanto como sea necesario, trate de ser flexible. A veces vale la pena incluso descartar algunas pruebas y sacrificar la fiabilidad en aras de la velocidad y la simplicidad.

La mayoría de las recomendaciones a continuación se derivan de este principio.
Estas listoSección 1. Anatomía de la prueba.
1.1 El nombre de cada prueba debe constar de tres partes
Que hacer El informe de prueba debe indicar si la revisión actual de la aplicación cumple con los requisitos de aquellas personas que no están familiarizadas con el código: probadores involucrados en el despliegue de ingenieros de DevOps, así como usted mismo en dos años. Será mejor si las pruebas informan la información en el idioma de los requisitos, y sus nombres constan de tres partes:
- ¿Qué se está probando exactamente? Por ejemplo, el método
ProductsService.addNewProduct
. - ¿Bajo qué condiciones y escenarios? Por ejemplo, el precio no se pasa al método.
- ¿Cuál es el resultado esperado? Por ejemplo, un nuevo producto no está aprobado.
De lo contrario. La implementación falla, la prueba llamada "Agregar producto" falla. ¿Entiendes qué funciona exactamente mal?
Nota Cada capítulo tiene un código de ejemplo y, a veces, una ilustración. Ver spoilers.
Ejemplos de códigoCómo hacerlo bien El nombre de la prueba consta de tres partes.
1.2 Estructurar las pruebas de acuerdo con el patrón AAA
Que hacer Cada prueba debe constar de tres secciones claramente separadas: Organizar (preparación), Actuar (acción) y Afirmar (resultado). Adherirse a dicha estructura asegura que el lector de su código no tenga que usar el procesador cerebral para comprender el plan de prueba:
Organizar: todo el código que lleva al sistema al estado según el escenario de prueba. Esto puede incluir crear una instancia del módulo en el diseñador de prueba, agregar registros a la base de datos, crear apéndices en lugar de objetos y cualquier otro código que prepare el sistema para la ejecución de la prueba.
Ley: ejecución de código como parte de una prueba. Por lo general, solo una línea.
Afirmar: asegúrese de que el valor obtenido cumpla con las expectativas. Por lo general, solo una línea.
De lo contrario. No solo pasará largas horas trabajando con el código principal, sino que su cerebro también se hinchará por lo que debería ser un trabajo simple: por las pruebas.
Ejemplos de códigoCómo hacerlo bien Una prueba estructurada de acuerdo con el patrón AAA.
describe.skip('Customer classifier', () => { test('When customer spent more than 500$, should be classified as premium', () => {
Un ejemplo de antipatrón. Ninguna separación, en una sola pieza, es más difícil de interpretar.
test('Should be classified as premium', () => { const customerToClassify = {spent:505, joined: new Date(), id:1} const DBStub = sinon.stub(dataAccess, "getCustomer") .reply({id:1, classification: 'regular'}); const receivedClassification = customerClassifier.classifyCustomer(customerToClassify); expect(receivedClassification).toMatch('premium'); });
1.3 Describa las expectativas en el lenguaje del producto: estado al estilo de BDD
Que hacer La programación de pruebas en un estilo declarativo permite al usuario comprender de inmediato la esencia sin gastar un solo ciclo de procesador cerebral. Cuando escribe código imperativo empaquetado en lógica condicional, el lector tiene que hacer un gran esfuerzo. Desde este punto de vista, debe describir las expectativas en un lenguaje similar al humano en un estilo de BDD declarativo utilizando expect / should y no utilizando un código personalizado. Si en Chai y Jest no hay una afirmación necesaria, que a menudo se repite, entonces puede
expandir el emparejador Jest o escribir
su propio complemento para Chai .
De lo contrario. El equipo escribirá menos pruebas y decorará pruebas molestas
with .skip()
.
Ejemplos de códigoUn ejemplo usando Mocha .
Un ejemplo de antipatrón. Para comprender la esencia de la prueba, el usuario se ve obligado a pasar por un código imperativo bastante largo.
it("When asking for an admin, ensure only ordered admins in results" , ()={
Cómo hacerlo bien Leer esta prueba declarativa es sencillo.
it("When asking for an admin, ensure only ordered admins in results" , ()={
1.4 Adhiérase a las pruebas de recuadro negro: pruebe solo los métodos públicos
Que hacer Probar el interior conducirá a una gran sobrecarga y no producirá casi nada. Si su código o API proporciona los resultados correctos, ¿vale la pena pasar tres horas probando CÓMO funciona internamente y luego también admitir estas pruebas frágiles? Cuando verifica el comportamiento público, simultáneamente verifica implícitamente la implementación en sí, sus pruebas fallarán solo si hay un problema específico (por ejemplo, salida incorrecta). Este enfoque también se llama prueba de comportamiento. Por otro lado, si está probando las partes internas (el método del "recuadro blanco"), en lugar de planificar la salida de los componentes, se centrará en pequeños detalles, y sus pruebas pueden romperse debido a pequeñas alteraciones del código, incluso si los resultados son correctos, pero La escolta tomará muchos más recursos.
De lo contrario. Sus pruebas se comportarán como un
niño gritando "¡Lobo!" : Informar en voz alta falsos positivos (por ejemplo, la prueba falla debido a un cambio en el nombre de una variable privada). No es sorprendente que pronto las personas comiencen a ignorar las notificaciones de CI, y algún día se perderán un error real ...
Ejemplos de códigoUn ejemplo de antipatrón. probando el interior sin una buena razón.
Un ejemplo usando Mocha .
class ProductService{
1.5 Elija la implementación simulada correcta: evite objetos falsos en favor de trozos y espías
Que hacer Las implementaciones simuladas (dobles de prueba) son un mal necesario porque están asociadas con las partes internas de la aplicación, y algunas son de gran valor (
refresca la memoria de implementaciones imitadas: objetos falsos (simulacros), stubs (stubs) y objetos espías (espías) ) Sin embargo, no todas las técnicas son equivalentes. Los espías y los trozos están diseñados para probar los requisitos, pero tienen un efecto secundario inevitable: también afectan ligeramente el interior. Y los objetos falsos están diseñados para probar el interior, lo que conduce a una gran sobrecarga, como se describe en el capítulo 1.4.
Antes de usar implementaciones simuladas, hágase la pregunta más simple: "¿Utilizo esto para probar la funcionalidad que ha aparecido o puede aparecer en la documentación con requisitos?" Si no, huele a pruebas de caja blanca.
Por ejemplo, si desea averiguar si la aplicación se comporta como debería cuando el servicio de pago no está disponible, puede hacer un talón en su lugar y devolver "Sin respuesta" para verificar si el módulo bajo prueba devuelve el valor correcto. Por lo tanto, puede verificar el comportamiento / respuesta / salida de la aplicación en ciertos escenarios. También puede confirmar con la ayuda de un espía que cuando el servicio no estaba disponible, se envió la carta, también es una prueba de comportamiento, que se refleja mejor en la documentación con los requisitos ("Enviar una carta si no se puede guardar la información de pago"). Al mismo tiempo, si realiza un servicio de pago falso y se asegura de que se llame utilizando los tipos JS correctos, su prueba está dirigida a elementos internos que no están relacionados con la funcionalidad de la aplicación y que es probable que cambien a menudo.
De lo contrario. Cualquier refactorización de código implica encontrar y actualizar todos los objetos falsos en el código. Las pruebas de un amigo asistente se convierten en una carga.
Ejemplos de códigoUn ejemplo de antipatrón. Los objetos falsos son para las tripas.
Ejemplo usando Sinon .
it("When a valid product is about to be deleted, ensure data access DAL was called once, with the right product and right config", async () => {
Cómo hacerlo bien Los espías están diseñados para probar los requisitos, pero hay un efecto secundario: inevitablemente afectan el interior.
it("When a valid product is about to be deleted, ensure an email is sent", async () => {
1.6 No use "foo", use una entrada realista
Que hacer A menudo, los errores de producción se producen con datos de entrada muy específicos y sorprendentes. Cuanto más realistas sean los datos durante las pruebas, más probabilidades hay de detectar errores a tiempo. Para generar datos pseudo-reales que simulan la variedad y el tipo de datos de producción, use bibliotecas especiales, por ejemplo,
Faker . Dichas bibliotecas pueden generar números de teléfono realistas, apodos de usuarios, tarjetas bancarias, nombres de compañías, incluso el texto "lorem ipsum". Puede crear pruebas (además de pruebas unitarias, y no en lugar de ellas) que aleatorizan datos falsos para ajustar el módulo a una prueba, o incluso importar datos reales desde un entorno de producción. ¿Quieres ir aún más lejos? Lea el siguiente capítulo (sobre pruebas basadas en propiedades).
De lo contrario. Sus pruebas de desarrollo se verán exitosas usando entradas sintéticas como "Foo", y los datos de producción pueden fallar cuando un hacker
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
línea difícil como
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
@3e2ddsf . ##' 1 fdsfds . fds432 AAAA
.
Ejemplos de códigoUn ejemplo de antipatrón. Un conjunto de pruebas que se ejecuta con éxito debido al uso de datos poco realistas.
Un ejemplo usando Jest .
const addProduct = (name, price) =>{ const productNameRegexNoSpace = /^\S*$/;
Cómo hacerlo bien Aleatorizar la entrada realista.
it("Better: When adding new valid product, get successful confirmation", async () => { const addProductResult = addProduct(faker.commerce.productName(), faker.random.number());
1.7 Usar pruebas basadas en propiedades para validar múltiples combinaciones de entrada
Que hacer Por lo general, para cada prueba seleccionamos varias muestras de datos de entrada. Incluso si el formato de entrada es similar a los datos reales (vea el capítulo "No use" foo "), cubrimos solo unas pocas combinaciones de datos de entrada (método
('', true, 1)
, método
("string" , false" , 0)
Pero en funcionamiento, una API que se llama con cinco parámetros se puede llamar con miles de combinaciones diferentes, una de las cuales puede provocar un
bloqueo del proceso (
fuzzing ). ¿Qué pasaría si pudiera escribir una prueba que envíe automáticamente 1000 combinaciones de datos de entrada y ¿En qué combinaciones el código no devuelve la respuesta correcta? Lo mismo que hacemos con m todike prueba basada en las propiedades: mediante el envío de todas las combinaciones posibles de los datos de entrada en la unidad de prueba que aumentar la posibilidad de una detección de errores, por ejemplo, tenemos un método.
addNewProduct(id, name, isDiscount)
Apoyo a su biblioteca llamará a este método con una serie de combinaciones.
(, , )
, por ejemplo,
(1, "iPhone", false)
,
(2, "Galaxy", true)
, etc. Puede realizar pruebas en función de las propiedades utilizando su corredor de prueba favorito (Mocha, Jest etc.) y bibliotecas como
js- verified o
testcheck (tiene una documentación mucho mejor). También puede
probar la biblioteca de verificación rápida , que ofrece características adicionales y está activamente acompañada por el autor.
De lo contrario. Está eligiendo sin pensar los datos de entrada para la prueba, que cubre solo las rutas de ejecución de código que funcionan bien. Desafortunadamente, esto reduce la efectividad de las pruebas como medio para detectar errores.
Ejemplos de códigoCómo hacerlo bien Prueba numerosas combinaciones con el test de mocha-test.
require('mocha-testcheck').install(); const {expect} = require('chai'); const faker = require('faker'); describe('Product service', () => { describe('Adding new', () => {
1.8 Si es necesario, use solo tomas cortas y en línea.
Que hacer Cuando necesite realizar una
prueba basada en instantáneas , use solo instantáneas cortas sin todo el extra (por ejemplo, en 3-7 líneas), incluidas como parte de la prueba (
Instantánea en línea ), y no como archivos externos. Seguir esta recomendación mantendrá sus pruebas evidentes y más confiables.
Por otro lado, las guías y herramientas de "instantánea clásica" nos provocan que almacenemos archivos grandes (por ejemplo, marcado para renderizar componentes o resultados de API JSON) en medios externos y comparar los resultados con la versión guardada cada vez que se ejecuta la prueba. Puede, por ejemplo, asociar implícitamente nuestra prueba con 1000 líneas que contienen 3000 valores que el autor de la prueba nunca vio sobre lo que no había esperado. ¿Por qué es esto malo? Porque hay 1000 razones para que la prueba falle. Incluso una línea puede invalidar una instantánea, y esto puede suceder a menudo. Cuanto Después de cada espacio, comentario o cambio menor en CSS o HTML. Además, el nombre de la prueba no le informará sobre la falla, ya que solo verifica que 1000 líneas no hayan cambiado, y también alienta al autor de la prueba a tomar el tiempo que desee un documento largo que no pudo analizar y verificar. Todos estos son síntomas de una prueba oscura y apresurada que no tiene una tarea clara y está tratando de lograr demasiado.
Vale la pena señalar que hay varias situaciones en las que es aceptable usar imágenes largas y externas, por ejemplo, al confirmar el esquema, y no los datos (extracción de valores y enfoque en los campos), o cuando los documentos recibidos rara vez cambian.
De lo contrario. Las pruebas de IU fallan. El código se ve bien, los píxeles ideales se muestran en la pantalla, entonces, ¿qué sucede? Su prueba con instantáneas acaba de revelar la diferencia entre el documento original y el recién recibido: se agregó un carácter de espacio al marcado ...
Ejemplos de códigoUn ejemplo de antipatrón. Asociar una prueba con algunas 2000 líneas de código desconocidas.
it('TestJavaScript.com is renderd correctly', () => {
Cómo hacerlo bien Las expectativas son visibles y están en el centro de atención.
it('When visiting TestJavaScript.com home page, a menu is displayed', () => {
1.9 Evite bancos de pruebas globales y datos iniciales, agregue datos a cada prueba por separado
Que hacer De acuerdo con la regla de oro (capítulo 0), cada prueba debería agregar y funcionar dentro de su propio conjunto de filas en la base de datos para evitar enlaces, y fue más fácil para los usuarios comprender la prueba. En realidad, los evaluadores a menudo violan esta regla, antes de ejecutar pruebas que llenan la base de datos con datos iniciales (semillas) (
también llamados "banco de pruebas" ) para aumentar la productividad. , (. « »), . . , , (, ).
. , , , ? , , , .
. - .
before(() => {
. , .
it("When updating site name, get successful confirmation", async () => {
1.10 ,
. , - , try-catch-finally , . ( ), .
Chai:
expect(method).to.throw
( Jest:
expect(method).toThrow()
). , , . , , .
. (, CI-) , .
. , try-catch .
/it("When no product name, it throws error 400", async() => { let errorWeExceptFor = null; try { const result = await addNewProduct({name:'nest'});} catch (error) { expect(error.code).to.equal('InvalidInput'); errorWeExceptFor = error; } expect(errorWeExceptFor).not.to.be.null;
. , , , QA .
it.only("When no product name, it throws error 400", async() => { expect(addNewProduct)).to.eventually.throw(AppError).with.property('code', "InvalidInput"); });
1.11
. :
- smoke-,
- IO-less,
- , , ,
- , pull request', .
, , , #cold #api #sanity. . , Mocha :
mocha — grep 'sanity'
.
. , , , , , , , .
. '#cold-test' (Cold=== , - , ).
1.12
. , Node.js . , Node.
TDD . , , , .
-- , - . , , . , . , , , , (, ..).
. , .
2:
️2.1 :
. 10 , . . , 10 (, , ), , ,
? ?
: 2019- , TDD , , , . , , ,
. IoT-, Kafka RabbitMQ, , - . , , ? (, , ), , - .
( ) , , (« API, , !» (consumer-driven contracts)). , : , , , .
: TDD - . TDD , . , .
. ROI, Fuzz, , 10 .
. Cindy Sridharan 'Testing Microservices — the sane way'

Un ejemplo:
2.2
. , . , . , , ? — . : TDD-, .
«», API, , (, , in-memory ), , , . , , « », .
. , , 20 %.
. Express API ( ).

2.3 , API
. , ( ). - , ! — , , . «
-22 » : , , .
(consumer-driven contracts) PACT : , … ! PACT — «», . PACT- — . , API CI, .
. — .
.
2.4
. , Express-. . , , , JS- {req,res}. , (,
Sinon ) {req,res}, , .
node-mock-http {req,res} . , , HTTP-, res- (. ).
. Express- === .
2.5
. . CI- , . (, ), (, ), .
Sonarqube (2600+
)
Code Climate (1500+
). ::
Keith Holliday. , .
. CodeClimate, :

2.6 , Node
. , . ( ) . , - , ? ? , API 50 % ? , Netflix - (
Chaos Engineering ). : , . , Netflix,
chaos monkey , , , , - ( Kubernetes
kube-monkey , ). , . , , Node- , , v8 1,7 , UX , ?
node-chaos (-), , Node.
. , production .
. Node-chaos , Node.js, .

2.7 ,
. ( 0), , , . , (seeds) (
« » ) . , (. « »), , . . , , (, ).
. , , , ? , , , .
. - .
before(() => {
. , .
it("When updating site name, get successful confirmation", async () => {
3:
3.1. UI
. , , , . , , ( HTML CSS) . , (, , , ), , , .
. 10 , 500 (100 = 1 ) - - .
. .
test('When users-list is flagged to show only VIP, should display only VIP members', () => {
. UI . test('When flagging to show only VIP, should display only VIP members', () => {
3.2 HTML- ,
. HTML- , . , , CSS-. , 'test-id-submit-button'. . , , .
. , , . — , , Ajax . . , CSS 'thick-border' 'thin-border'
. , .
. CSS-.
<!-- the markup code (part of React component) --> <span id="metric" className="d-flex-column">{value}</span> <!-- what if the designer changes the classs? -->
3.3
. , , . , , . , — - , (.
« » ). (, ) , .
, : , . ( ) . , .
. , . ?
. .
class Calendar extends React.Component { static defaultProps = {showFilters: false} render() { return ( <div> A filters panel with a button to hide/show filters <FiltersPanel showFilter={showFilters} title='Choose Filters'/> </div> ) } } //Examples use React & Enzyme test('Realistic approach: When clicked to show filters, filters are displayed', () => { // Arrange const wrapper = mount(<Calendar showFilters={false} />) // Act wrapper.find('button').simulate('click'); // Assert expect(wrapper.text().includes('Choose Filter')); // This is how the user will approach this element: by text })
. .
test('Shallow/mocked approach: When clicked to show filters, filters are displayed', () => {
3.4 .
. (, ). (,
setTimeOut
) , . (,
Cypress cy.request('url') ), API,
wait(expect(element)) @testing-library/DOM . , API, , . , ,
hurry-up the clock . — , , ( ). , , - npm- , ,
wait-for-expect .
. , . , . .
. E2E API (Cypress).
. , DOM- (@testing-library/dom).
. .
test('movie title appears', async () => {
3.5.
. - , . , , . :
pingdom , AWS CloudWatch
gcp StackDriver , , SLA. , , (,
lighthouse ,
pagespeed ), . — , :
,
(TTI) . , , , , , DOM, SSL . , CI, 247 CDN.
. , , , , - CDN.
. Lighthouse .

3.6 API
. ( 2), , , ( ). API (,
Sinon ,
Test doubles ), API. . API , ( ). API, . , , API . , : .
. , API 100 , 20 .
3.7 ,
. E2E (end-to-end, ) UI (. 3.6). , , . , , - . , — (, ), . - , , UI-
Cypress Pupeteer . , : 50 , , . 10 . , , , — . , .
. UI , , ( , UI) .
3.8
. , API , , . (before-all), - . , : . , . - API- . , . (, ), , , . , : , API (. 3.6).
. , 200 , 100 , 20 .
. (before-all), (before-each) (, Cypress).
Cypress .
let authenticationToken;
3.9 smoke-,
. production- , , . , , , , . smoke- . production, , , . , smoke- , .
. , , production . /Payment.
. Smoke- .
it('When doing smoke testing over all page, should load them all successfully', () => {
3.10
. , . «» , , , , . , ( ) , , -, , , . « », .
. ,
Cucumber JavaScript .
StoryBook UI- , (, , , ..) , . , , .
. , .
. cucumber-js.
. Storybook , .

3.11
. , . , . , . , - . , . , , , . , - . UI « ». , (,
wraith , PhantomCSS), . (,
Applitools ,
Perci.io ) , , « » (, ), DOM/CSS, .
. , ( ) , ?
. : , .

. wraith UI.
# Add as many domains as necessary. Key will act as a label domains: english: "http://www.mysite.com" # Type screen widths below, here are a couple of examples screen_widths: - 600 - 768 - 1024 - 1280 # Type page URL paths below, here are a couple of examples paths: about: path: /about selector: '.about' subscribe: selector: '.subscribe' path: /subscribe
4:
4.1 (~80 %),
. — , . , . — (, ), . ? , 10-30 % . 100 % , . . , : Airbus, ; , 50 % . , , 80 % (
Fowler: «in the upper 80s or 90s» ), , , .
: (CI), (
Jest ) , . , . , ( ) — . , — , , . , .
. . , , . .
.
. ( Jest).

4.2 ,
. , . , , , , . , , - , .
PricingCalculator
, , , 10 000 … , , . , . 80- , . : , , , . , - .
. , , , .
. ? , QA . : , - . , - API .

4.3
. : 100 %, . ¿Cómo es eso? , , , . . - : , , , .
, . JavaScript-
Stryker :
- « ». ,
newOrder.price===0
newOrder.price!=0
. «» .
- , , : , . , , .
, , , .
. , 85- 85 % .
. 100 %, 0 %.
function addNewOrder(newOrder) { logger.log(`Adding new order ${newOrder}`); DB.save(newOrder); Mailer.sendMail(newOrder.assignee, `A new order was places ${newOrder}`); return {approved: true}; } it("Test addNewOrder, don't use such test names", () => { addNewOrder({asignee: "John@mailer.com",price: 120}); });
. Stryker reports, , ().

4.4 -
. ESLint. ,
eslint-plugin-mocha , (
describe()
),
, .
eslint-plugin-jest , ( ).
. 90- , , , . , .
. , , .
describe("Too short description", () => { const userToken = userService.getDefaultToken()
5: CI
5.1 ,
. — . , . , ( !). , . (
ESLint standard Airbnb ), . ,
eslint-plugin-chai-expect , .
Eslint-plugin-promise ( ).
Eslint-plugin-security , DOS-.
eslint-plugin-you-dont-need-lodash-underscore , , V8, ,
Lodash._map(…)
.
. , , . Que esta pasando , , . . , , .
. , . , ESLint production-.

5.2
. CI , , ..? ,
. Por qué : (1) -> (2) -> (3) . , , .
, , , , - .
CI- ( ,
CircleCI local CLI ) . ,
wallaby , ( ) . npm- package.json, , (, , , ). (non-zero exit code)
concurrently . — ,
npm run quality
. githook (
husky ).
. , .
. Npm-, , , .
"scripts": { "inspect:sanity-testing": "mocha **/**--test.js --grep \"sanity\"", "inspect:lint": "eslint .", "inspect:vulnerabilities": "npm audit", "inspect:license": "license-checker --failOn GPLv2", "inspect:complexity": "plato .", "inspect:all": "concurrently -c \"bgBlue.bold,bgMagenta.bold,yellow\" \"npm:inspect:quick-testing\" \"npm:inspect:lint\" \"npm:inspect:vulnerabilities\" \"npm:inspect:license\"" }, "husky": { "hooks": { "precommit": "npm run inspect:all", "prepush": "npm run inspect:all" } }
5.3 production-
. — CI-. . —
Docker-compose . (, ) production-.
AWS Local AWS-.
, serverless
AWS SAM Faas-.
Kubernetes CI-, . , « Kubernetes»
Minikube MicroK8s , , . « Kubernetes»: CI- (,
Codefresh ) Kubernetes-, CI- ; .
. .
: CI-, Kubernetes-
(Dynamic-environments Kubernetes )
deploy: stage: deploy image: registry.gitlab.com/gitlab-examples/kubernetes-deploy script: - ./configureCluster.sh $KUBE_CA_PEM_FILE $KUBE_URL $KUBE_TOKEN - kubectl create ns $NAMESPACE - kubectl create secret -n $NAMESPACE docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_REGISTRY_USER" --docker-password="$CI_REGISTRY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" - mkdir .generated - echo "$CI_BUILD_REF_NAME-$CI_BUILD_REF" - sed -e "s/TAG/$CI_BUILD_REF_NAME-$CI_BUILD_REF/g" templates/deals.yaml | tee ".generated/deals.yaml" - kubectl apply --namespace $NAMESPACE -f .generated/deals.yaml - kubectl apply --namespace $NAMESPACE -f templates/my-sock-shop.yaml environment: name: test-for-ci
5.4
. , , . , 500 , , . , CI- (
Jest ,
AVA Mocha ) , . CI- (!), . , CLI , , .
. — , .
5.5
. , . 10 ? CI- npm-
license check plagiarism check ( ), , , Stackoveflow .
. , , .
.

5.6
. , Express, .
npm audit ,
snyk ( ). CI .
. . .
: NPM Audit

5.7
. package-lock.json Yarn npm ( ): .
npm install
npm update
, . , — . , package.json
ncu .
, . :
- CI , , npm outdated npm-check-updates (ncu). .
- , pull request' .
: ? , ( ,
eslint-scope ). « »:
latest , , (, 1.3.1, — 1.3.8).
. , .
5.8 CI-, Node
. , Node . , Node.
- . , Jenkins .
- Docker.
- , . . smoke-, (, , ) .
- , , , , , .
- , . , -. - ( ).
- . .
- , , .
- (, Docker-).
- , .
node_modules
.
. , .
5.9 : CI-, Node
. , , . Node, CI . , MySQL, Postgres. CI- «», MySQl, Postgres Node. , - (, ). CI, , .
. - ?
: Travis ( CI) Node.
language: node_js node_js: - "7" - "6" - "5" - "4" install: - npm install script: - npm run test