rmanguinho / clean-ts-api

API em NodeJs usando Typescript, TDD, Clean Architecture, Design Patterns e SOLID principles
https://rmanguinho.github.io/
GNU General Public License v3.0
1.86k stars 498 forks source link

Baixa performance nos testes causada pelo banco de dados (sugestão) #51

Open christian-gama opened 2 years ago

christian-gama commented 2 years ago

Salve.

Notei que todo teste faz uma nova conexão ao banco de dados e logo em seguida desconecta. Eu estava fazendo exatamente dessa forma em um projeto pessoal meu que tem bastante teste. Os testes de integração levavam cerca de 2 minutos para concluir. Para contornar esse problema, criei um arquivo integration.test.ts que faz uma leitura de todos os testes de integração (que são os que têm conexão ao banco de dados) e encapsulei todos os testes dentro desse arquivo. Só certifique-se de rodar apenas o integration.test.ts.

O resultado foi impressionante, caiu de 2 minutos para apenas 21 segundos!! A alta performance se dá por conta de apenas uma conexão ao banco de dados, ao invés de se conectar/desconectar em cada teste.

// integration.test.ts
const tests = (): void =>
  glob.sync(`${resolve(__dirname)}/**/*.ts`).forEach((content) => {
    if (content.match(/\.(test|steps)\.ts$/) && !content.match(/integration\.test\.ts$/)) {
      require(content)
    }
  })

describe('integration tests', () => {
  afterAll(async () => {
    const client = makeMongoDb()

    await client.disconnect()
  })

  beforeAll(async () => {
    await MongoAdapter.connect(global.__MONGO_URI__)
  })

  tests()
})

Caso eu queira rodar apenas um teste, ao invés de ter que rodar todos, fiz uma verificação antes em cada teste, pois assim torna os testes flexíveis. Dessa forma posso depurar apenas um teste, caso seja necessário.

// user.test.ts

describe ...
  let isConnected = true

  afterAll(async () => {
    if (!isConnected) await client.disconnect()
  })

  beforeAll(async () => {
    isConnected = MongoAdapter.client != null
    if (!isConnected) await MongoAdapter.connect(global.__MONGO_URI__)
  })
...

Conectando/desconectando em cada teste (a forma que tava antes):

Sem

Conectando/desconectando apenas uma vez antes de todos os testes:

com
rmanguinho commented 2 years ago

Bem interessante amigo. Assim que der irei analisar seu código. Obrigado pela dica!

On Fri, 29 Oct 2021 at 02:38 Christian Gama @.***> wrote:

Salve.

Notei que todo teste faz uma nova conexão ao banco de dados e logo em seguida desconecta. Eu estava fazendo exatamente dessa forma em um projeto pessoal meu que tem bastante teste. Os testes de integração levavam cerca de 2 minutos para concluir. Para contornar esse problema, criei um arquivo integration.test.ts que faz uma leitura de todos os testes de integração (que são os que têm conexão ao banco de dados) e encapsulei todos os testes dentro desse arquivo. Nos testes eu exportei os blocos de describe em export default (): void => {describe...)

O resultado foi impressionante, caiu de 2 minutos para apenas 21 segundos!! A alta performance se dá por conta de apenas uma conexão ao banco de dados, ao invés de se conectar/desconectar em cada teste.

const tests = glob

.sync(${resolve(__dirname)}/**/*.ts)

.map((content) => {

if (content.match(/\.(test)\.ts$/) && !content.match(/integration\.test\.ts$/)) {

  return require(content)

} else return null

})

.filter((content: any) => content != null)

describe('integration tests', () => {

afterAll(async () => {

const client = makeMongoDb()

await client.disconnect()

})

beforeAll(async () => {

await MongoAdapter.connect(global.__MONGO_URI__)

})

tests.forEach((test) => test.default())

})

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rmanguinho/clean-ts-api/issues/51, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABDASG65WWIQHDIO6B7457TUJIXNPANCNFSM5G6PP66Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

-- Rodrigo Manguinho

christian-gama commented 2 years ago

Se não estivéssemos usando Typescript, daria para usarmos o setupFile do jest, onde ele roda algo antes de todos os testes. Mas por limitação deles, o setupFile roda antes de transpilar para o Typescript, aí dá erro. Essa foi a melhor solução que encontrei até agora. Me avise se encontrar uma solução melhor, por favor. 😄

Só uma observação, pois talvez aconteça com você. Os testes das factories não podem estar junto com esse arquivo, pois eles mockam as validações e bugam tudo. Não soube como resetar o mock, então preferi deixar rodando de forma separada os testes das factories.

rmanguinho commented 2 years ago

Beleza!

On Fri, 29 Oct 2021 at 11:15 Christian Gama @.***> wrote:

Se não estivéssemos usando Typescript, daria para usarmos o setupFile do jest, onde ele roda algo antes de todos os testes. Mas por limitação deles, o setupFile roda antes de transpilar para o Typescript, aí dá erro. Essa foi a melhor solução que encontrei até agora. Me avise se encontrar uma solução melhor, por favor. 😄

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rmanguinho/clean-ts-api/issues/51#issuecomment-954780230, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABDASG4DU7HYLPXLYOGD4V3UJKT7HANCNFSM5G6PP66Q . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

-- Rodrigo Manguinho