{"id":12389,"date":"2021-11-02T08:00:35","date_gmt":"2021-11-02T15:00:35","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=12389"},"modified":"2025-06-13T21:03:49","modified_gmt":"2025-06-14T04:03:49","slug":"functional-and-integration-testing-fit-framework","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/pt\/functional-and-integration-testing-fit-framework\/","title":{"rendered":"Estrutura de testes funcionais e de integra\u00e7\u00e3o (FIT)"},"content":{"rendered":"<p><span style=\"font-weight: 400\">Este blog descreve o projeto e o desenvolvimento da estrutura de teste, ou seja, a estrutura FIT para transa\u00e7\u00f5es do Couchbase em um ambiente distribu\u00eddo. Come\u00e7aremos apresentando uma vis\u00e3o arquitet\u00f4nica de alto n\u00edvel e, em seguida, o acompanharemos no desenvolvimento da estrutura.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Vamos analisar v\u00e1rios problemas envolvidos no teste dos SDKs de transa\u00e7\u00f5es e as solu\u00e7\u00f5es para eles, e exemplos relevantes ser\u00e3o usados durante o desenvolvimento da estrutura. Mesmo que nem todos os detalhes t\u00e9cnicos da estrutura sejam mencionados neste blog, ele definitivamente tenta dar uma vis\u00e3o hol\u00edstica da estrutura.<\/span><\/p>\n<p><span style=\"font-weight: 400\">O Couchbase oferece transa\u00e7\u00f5es em v\u00e1rios SDKs: Java, Dotnet e CXX por enquanto e com um plano para oferecer suporte a outros SDKs em um futuro pr\u00f3ximo. O teste de SDKs que oferecem a mesma funcionalidade apresentaria v\u00e1rios problemas durante a automa\u00e7\u00e3o de testes. A redund\u00e2ncia da automa\u00e7\u00e3o de testes \u00e9 o primeiro que vem \u00e0 mente de todos. Al\u00e9m da redund\u00e2ncia, tamb\u00e9m temos que garantir que todos os SDKs tenham implementa\u00e7\u00f5es semelhantes das transa\u00e7\u00f5es do Couchbase. Por exemplo: o tratamento de erros \u00e9 feito exatamente da mesma forma por todos os SDKs. Esses s\u00e3o apenas alguns problemas. Com foco principal em Transa\u00e7\u00f5es, este blog apresentar\u00e1 v\u00e1rios problemas que enfrentamos ao testar v\u00e1rios SDKs e como n\u00f3s do Couchbase os resolvemos.<\/span><\/p>\n<p><b>Introdu\u00e7\u00e3o \u00e0s transa\u00e7\u00f5es do Couchbase<\/b><\/p>\n<p><span style=\"font-weight: 400\">As transa\u00e7\u00f5es ACID distribu\u00eddas garantem que, quando v\u00e1rios documentos precisam ser modificados, somente a modifica\u00e7\u00e3o bem-sucedida de todos justifica a modifica\u00e7\u00e3o de qualquer um, ou todas as modifica\u00e7\u00f5es ocorrem com sucesso ou nenhuma delas ocorre. A conformidade do Couchbase com as propriedades ACID pode ser encontrada em <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/data\/transactions.html\"><span style=\"font-weight: 400\">aqui<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><b>Transa\u00e7\u00f5es em ambientes distribu\u00eddos:\u00a0<\/b><\/p>\n<p><b>Cluster de n\u00f3 \u00fanico: <\/b><span style=\"font-weight: 400\">As transa\u00e7\u00f5es do Couchbase funcionam em clusters de v\u00e1rios n\u00f3s e de um \u00fanico n\u00f3.  No entanto, a configura\u00e7\u00e3o do cluster deve ser suportada por <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/data\/durability.html#majority\"><span style=\"font-weight: 400\">Couchbase<\/span><\/a><span style=\"font-weight: 400\">.<\/span><\/p>\n<p><b>Suporte a transa\u00e7\u00f5es para consultas N1QL:<\/b><span style=\"font-weight: 400\"> Assegurar que pelo menos um dos n\u00f3s do cluster tenha servi\u00e7o de consulta<\/span><\/p>\n<p><b>Teste do SDK do Couchbase Transactions:<\/b><\/p>\n<p><span style=\"font-weight: 400\">Durante a fase de projeto da estrutura, uma an\u00e1lise profunda do plano de teste e de sua automa\u00e7\u00e3o nos colocou diante de v\u00e1rios desafios. Abaixo est\u00e3o alguns dos principais desafios e suas resolu\u00e7\u00f5es. A seguir, discutiremos o problema e sua solu\u00e7\u00e3o. Tamb\u00e9m veremos o progresso do desenvolvimento da estrutura junto com essas discuss\u00f5es de problemas.<\/span><\/p>\n<p><b>Problema 1: Problema de redund\u00e2ncia:<\/b><\/p>\n<p><span style=\"font-weight: 400\">No Couchbase, atualmente oferecemos suporte a transa\u00e7\u00f5es em tr\u00eas SDKs diferentes: Java, Dotnet e CXX. Em um futuro pr\u00f3ximo, ofereceremos suporte a mais alguns SDKs, incluindo o Golang. Isso claramente fornece ao QE um problema de redund\u00e2ncia, ou seja, talvez tenhamos que automatizar o mesmo caso de teste v\u00e1rias vezes, uma vez para cada SDK.\u00a0<\/span><\/p>\n<p><b>Resolu\u00e7\u00e3o: <\/b><span style=\"font-weight: 400\">Cada caso de teste pode ser classificado em tr\u00eas partes principais:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Prepara\u00e7\u00e3o do teste, por exemplo: dados de teste, infraestrutura de teste etc,\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Execu\u00e7\u00e3o de testes, por exemplo: execu\u00e7\u00e3o de opera\u00e7\u00f5es de transa\u00e7\u00e3o, ou seja, inserir, substituir etc. e\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Valida\u00e7\u00e3o de resultados.<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">Uma an\u00e1lise mais detalhada dessas tr\u00eas partes revela que o teste do SDK est\u00e1 envolvido apenas na fase de execu\u00e7\u00e3o do teste, enquanto a prepara\u00e7\u00e3o do teste e a valida\u00e7\u00e3o do resultado s\u00e3o, na verdade, independentes do SDK, ou seja, n\u00e3o importa qual SDK \u00e9 usado. Isso nos levou a projetar uma estrutura que consiste em duas partes, ou seja, driver e executor. O driver cuida de toda a prepara\u00e7\u00e3o do teste e da valida\u00e7\u00e3o dos resultados. O driver conduz a execu\u00e7\u00e3o do teste, mas apenas de forma abstrata (aprenderemos mais sobre isso abaixo), ou seja, emite comandos para o executor e o executor os recebe e realiza a execu\u00e7\u00e3o real do teste.<\/span><\/p>\n<p><b>Estrutura do FIT <\/b><span style=\"font-weight: 400\">\u00e9 projetado em um<\/span> <span style=\"font-weight: 400\">modelo cliente-servidor em que o driver atua como cliente e o executor como servidor.<\/span><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-12390 size-full\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2021\/11\/FIT-Framework-Architecture.png\" alt=\"FIT Framework Architecture\" width=\"960\" height=\"540\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/FIT-Framework-Architecture.png 960w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/FIT-Framework-Architecture-300x169.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/FIT-Framework-Architecture-768x432.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/FIT-Framework-Architecture-20x11.png 20w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" \/><\/p>\n<p><b>Motorista: <\/b><span style=\"font-weight: 400\">Consiste em toda a prepara\u00e7\u00e3o de testes e valida\u00e7\u00e3o de resultados. Todos os testes s\u00e3o os testes cl\u00e1ssicos do Junit e podem ser executados como um \u00fanico teste individual ou como um conjunto de testes espec\u00edfico ou um conjunto de testes completo. Todos os testes s\u00e3o escritos uma e somente uma vez. Esses testes podem ser reutilizados em todos os SDKs.<\/span><\/p>\n<p><b>Int\u00e9rprete:<\/b><span style=\"font-weight: 400\"> Esse \u00e9 um aplicativo simples escrito uma vez para cada SDK. Dentro de um driver, cada teste \u00e9 moldado na forma de um objeto Java e enviado para o <\/span><a href=\"https:\/\/grpc.io\/\"><span style=\"font-weight: 400\">gRPC<\/span><\/a><span style=\"font-weight: 400\"> Camada. O protocolo gRPC faz o trabalho de converter esse objeto Java em um objeto de teste espec\u00edfico da linguagem e o envia para o executor. O executor obt\u00e9m esse objeto de teste, l\u00ea as instru\u00e7\u00f5es e executa as opera\u00e7\u00f5es de transa\u00e7\u00e3o necess\u00e1rias. Quando a transa\u00e7\u00e3o \u00e9 conclu\u00edda, o executor recupera o resultado e o envia de volta ao driver por meio do protocolo gRPC<\/span><\/p>\n<p><span style=\"font-weight: 400\">Quando o driver recebe o objeto de resultado, ele prossegue com a valida\u00e7\u00e3o do resultado<\/span><b>Processo de desenvolvimento de testes:<\/b><span style=\"font-weight: 400\"> Agora que temos uma ideia de n\u00edvel superior de como o driver e o performer operam dentro da estrutura do FIT, vamos ver o aspecto t\u00e9cnico e como eles interagem entre si usando alguns testes de exemplo simples.<\/span><\/p>\n<p><b>Exemplo 1: Teste de transa\u00e7\u00f5es com uma \u00fanica opera\u00e7\u00e3o: Opera\u00e7\u00e3o b\u00e1sica de \"substitui\u00e7\u00e3o\"\u00a0<\/b><\/p>\n<p><b>C\u00f3digo do motorista:\u00a0<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre class=\"\"> \u00a0 @Test\r\n \u00a0\u00a0public void oneUpdateCommitted() {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0collection.upsert(docId, initial); \u00a0 \/\/ Test Preparation\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TransactionResult result = TransactionBuilder.create(shared)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.replace(docId, updated)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.sendToPerformer();\u00a0 \u00a0 \u00a0 \/\/ Test Execution\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Result validation\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertCompletedInSingleAttempt(shared, collection, result);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertDocExistsAndNotInTransactionAndContentEquals(collection, docId, updated);\r\n \u00a0\u00a0}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400\">Como voc\u00ea pode ver, todos os testes s\u00e3o sempre escritos apenas uma vez e como testes Junit.<\/span><\/p>\n<p><span style=\"font-weight: 400\">A prepara\u00e7\u00e3o do teste e a valida\u00e7\u00e3o do resultado s\u00e3o independentes do SDK e, portanto, s\u00e3o feitas no pr\u00f3prio teste Junit.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">No entanto, a parte de execu\u00e7\u00e3o do teste \u00e9 feita de forma abstrata. Na parte superior, parecer\u00e1 que est\u00e1 sendo executada no pr\u00f3prio driver. Mas ele se envolve em computa\u00e7\u00e3o distribu\u00edda seguindo a chamada de procedimento remoto. Todo o teste \u00e9 convertido em um objeto Java, chamado de objeto \"TransactionBuilder\" em nossa estrutura FIT, usando a classe Transaction Builder e, em seguida, enviado ao executor por meio da camada gRPC usando o m\u00e9todo \"sendToPerfomer\".\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Neste exemplo, em que estamos tentando testar a opera\u00e7\u00e3o de substitui\u00e7\u00e3o de transa\u00e7\u00f5es, criamos um objeto Java que ter\u00e1 todos os detalhes:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Identifica\u00e7\u00e3o do documento no qual a transa\u00e7\u00e3o deve ser executada\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Valor atualizado, ou seja, o novo valor que queremos que a transa\u00e7\u00e3o imponha ao documento<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Opera\u00e7\u00e3o de transa\u00e7\u00e3o, nesse caso, \u00e9 \"substituir\"<\/span><\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">Depois de criar esse objeto java, o sendToPerformer simplesmente invoca o <\/span><a href=\"https:\/\/grpc.io\/\"><span style=\"font-weight: 400\">gRPC<\/span><\/a><span style=\"font-weight: 400\"> para envi\u00e1-lo ao servidor.<\/span><\/p>\n<p><b>Consulte o c\u00f3digo do Java Performer: <\/b><a href=\"https:\/\/github.com\/couchbaselabs\/blog-fit-performer\/blob\/main\/basicPerformer.java\"><b>basicPerformer<\/b><\/a><\/p>\n<p><span style=\"font-weight: 400\">Portanto, na primeira etapa, o executor l\u00ea o objeto de teste e verifica a opera\u00e7\u00e3o que precisa executar. Em nosso exemplo, como se trata de uma opera\u00e7\u00e3o de substitui\u00e7\u00e3o, op.hasReplace() retornar\u00e1 true e op.hasInsert(), op.hasRemove() etc. retornar\u00e3o false.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Dentro do bloco de c\u00f3digo de substitui\u00e7\u00e3o, o executor recupera o ID do documento, o local do documento e o valor atualizado do documento. Depois que todas as informa\u00e7\u00f5es relevantes s\u00e3o recuperadas, o executor executa a transa\u00e7\u00e3o, ou seja, a opera\u00e7\u00e3o ctx.replace().<\/span><\/p>\n<p><span style=\"font-weight: 400\">Depois que a transa\u00e7\u00e3o \u00e9 executada com \u00eaxito, o resultado \u00e9 enviado de volta ao driver, que, da mesma forma, recupera as informa\u00e7\u00f5es relevantes do objeto de resultado e realiza a valida\u00e7\u00e3o do resultado.<\/span><\/p>\n<p><b>Exemplos de funcionalidades testadas: <\/b><span style=\"font-weight: 400\">Esse recurso da estrutura nos ajudou a testar o SDK de transa\u00e7\u00f5es n\u00e3o apenas para o conte\u00fado do documento, mas tamb\u00e9m para os metadados da transa\u00e7\u00e3o, ou seja, os metadados esperados est\u00e3o presentes sempre que necess\u00e1rio e os metadados s\u00e3o removidos sempre que necess\u00e1rio.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Agora que j\u00e1 temos algumas informa\u00e7\u00f5es t\u00e9cnicas sobre a estrutura FIT, vamos entrar em mais detalhes:<\/span><\/p>\n<p><b>Eg2: Teste de transa\u00e7\u00f5es com mais de uma opera\u00e7\u00e3o:<\/b><\/p>\n<p><b>C\u00f3digo do motorista:<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre class=\"\"> \u00a0 @Test\r\n \u00a0\u00a0\u00a0void insertReplaceTest() {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0collection.upsert(docId2, initial); \/\/Test preparation\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TransactionResult result = TransactionBuilder.create(shared)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.insert(docId1, initial)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.replace(docId2, updated)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.sendToPerformer();\u00a0 \/\/Actual Test Execution\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/\/Result validation\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertCompletedInSingleAttempt(shared, collection, result);\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertDocExistsAndNotInTransactionAndContentEquals(collection, docId1, initial);\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertDocExistsAndNotInTransactionAndContentEquals(collection, docId2, updated);\r\n \u00a0\u00a0\u00a0}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400\">Nesse teste, a transa\u00e7\u00e3o executa a inser\u00e7\u00e3o do documento com docId1 e a substitui\u00e7\u00e3o do documento com docId2. Portanto, temos que adicionar \"insert\" e \"replace\" ao objeto de teste e todas as informa\u00e7\u00f5es necess\u00e1rias para cada uma dessas opera\u00e7\u00f5es s\u00e3o enviadas ao executor.<\/span><\/p>\n<p><b>Consulte o c\u00f3digo do Java Performer: <\/b><a href=\"https:\/\/github.com\/couchbaselabs\/blog-fit-performer\/blob\/main\/performerSupportsTwoOps.java\"><b>performerSupportsTwoOps<\/b><\/a><\/p>\n<p><span style=\"font-weight: 400\">Como temos insert e replace, op.Insert retornar\u00e1 true e o executor recuperar\u00e1 as informa\u00e7\u00f5es necess\u00e1rias e executar\u00e1 a inser\u00e7\u00e3o e, em seguida, op.replace() retornar\u00e1 true e o executor executar\u00e1 as opera\u00e7\u00f5es de substitui\u00e7\u00e3o e retornar\u00e1 o resultado ao driver.<\/span><\/p>\n<p><b>Exemplos de funcionalidades testadas:<\/b><span style=\"font-weight: 400\"> Inicialmente, n\u00e3o oferecemos suporte a todas as opera\u00e7\u00f5es v\u00e1lidas de transa\u00e7\u00f5es m\u00faltiplas no mesmo documento na mesma transa\u00e7\u00e3o. Tamb\u00e9m foram testadas as opera\u00e7\u00f5es m\u00faltiplas regulares de transa\u00e7\u00f5es em documentos diferentes. Problemas como falhas nas transa\u00e7\u00f5es para substituir\/remover documentos e expira\u00e7\u00e3o foram bem testados com esse suporte<\/span><\/p>\n<p><span style=\"font-weight: 400\">Vimos em ambos os exemplos que se espera que a transa\u00e7\u00e3o seja bem-sucedida. No entanto, para cen\u00e1rios de casos negativos, esperamos que a transa\u00e7\u00e3o lance erros\/exce\u00e7\u00f5es. Esses erros\/exce\u00e7\u00f5es s\u00e3o espec\u00edficos do SDK e, portanto, precisam ser tratados no executor. Portanto, o driver precisa informar ao executor qual erro\/exce\u00e7\u00e3o deve ser exclu\u00eddo e o executor precisa fazer essa valida\u00e7\u00e3o<\/span><\/p>\n<p><b>Problema2 Verifica\u00e7\u00e3o de erros:<\/b><\/p>\n<ol>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Para causas diferentes, a transa\u00e7\u00e3o deve entender a causa e lan\u00e7ar os erros\/exce\u00e7\u00f5es relevantes. Portanto, tivemos que testar n\u00e3o apenas a funcionalidade das transa\u00e7\u00f5es, mas tamb\u00e9m os c\u00f3digos de erro e as exce\u00e7\u00f5es lan\u00e7adas por elas<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">O tratamento de exce\u00e7\u00f5es de transa\u00e7\u00e3o \u00e9 diferente para cada erro\/exce\u00e7\u00e3o: A exce\u00e7\u00e3o Documento n\u00e3o encontrado deve ser tratada de forma diferente de algumas exce\u00e7\u00f5es transit\u00f3rias\u00a0<\/span><\/li>\n<li style=\"font-weight: 400\"><span style=\"font-weight: 400\">Mesmo para a mesma exce\u00e7\u00e3o, o est\u00e1gio da transa\u00e7\u00e3o em que ela ocorre tamb\u00e9m resulta em um tratamento diferente. Por exemplo: os conflitos de grava\u00e7\u00e3o\/grava\u00e7\u00e3o para inser\u00e7\u00e3o\/substitui\u00e7\u00e3o s\u00e3o tratados de forma diferente das opera\u00e7\u00f5es de obten\u00e7\u00e3o.<\/span><\/li>\n<\/ol>\n<p><b>Resolu\u00e7\u00e3o: <\/b><span style=\"font-weight: 400\">O driver deve enviar c\u00f3digos para as causas e exce\u00e7\u00f5es para o executor. O executor ler\u00e1 os c\u00f3digos das causas de falha e os induzir\u00e1 usando Hooks.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Hooks s\u00e3o implementa\u00e7\u00f5es internas do Couchbase que ajudam a testar cen\u00e1rios de falha. Em nosso exemplo abaixo, estamos apenas tentando criar uma expira\u00e7\u00e3o antes de inserir um documento<\/span><\/p>\n<p><span style=\"font-weight: 400\">Quando a falha for induzida, o executor tamb\u00e9m esperar\u00e1 o erro\/exce\u00e7\u00e3o que essa transa\u00e7\u00e3o deve lan\u00e7ar. Se a exce\u00e7\u00e3o n\u00e3o for lan\u00e7ada ou se uma expectativa incorreta for lan\u00e7ada, o executor falhar\u00e1 nos testes e enviar\u00e1 a falha no objeto de resultado para o driver. O driver l\u00ea esse objeto de resultado e fornece a falha esperada e a real como sa\u00edda.<\/span><\/p>\n<p><b>Eg3: testar cen\u00e1rios de casos negativos :<\/b><\/p>\n<p><b>C\u00f3digo do motorista:<\/b><\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<pre class=\"\">@Test\r\n \u00a0\u00a0\u00a0void expiryDuringFirstOpInTransactionEntersExpiryOvertime() {\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0String docId = TestUtils.docId(collection, 0);\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TransactionResult result = TransactionBuilder.create(shared)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.injectExpiryAtPoint(StagePoints.HOOK_INSERT)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.insert(docId, updated, EXPECT_FAIL_EXPIRY)\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0.sendToPerformer();\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ResultValidator.assertNotStarted(collection, result);\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0DocValidator.assertDocDoesNotExist(collection, docId);\r\n \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0assertEquals(TransactionException.EXCEPTION_EXPIRED, result.getException());\r\n \u00a0\u00a0\u00a0}<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400\">Portanto, nesse teste, o driver est\u00e1 dizendo ao executor para executar a inser\u00e7\u00e3o e, em seguida, esperar que a transa\u00e7\u00e3o expire durante essa opera\u00e7\u00e3o de inser\u00e7\u00e3o. Enviamos o c\u00f3digo \"EXPECT_FAIL_EXPIRY\" para transmitir isso ao executor.<\/span><\/p>\n<p><b>Consulte o c\u00f3digo do Java Performer: <\/b><a href=\"https:\/\/github.com\/couchbaselabs\/blog-fit-performer\/blob\/main\/performerSupportsErrorHandling.java\"><b>performerSupportsErrorHandling<\/b><\/a><\/p>\n<p><b>Exemplos de funcionalidades testadas: <\/b><span style=\"font-weight: 400\">Todos os c\u00f3digos de erro e tratamento de exce\u00e7\u00f5es\/erros foram testados. Foram realizados testes funcionais relacionados a qualquer SDK que n\u00e3o oferecesse suporte ou n\u00e3o estivesse em sincronia com a funcionalidade acordada de tratamento de erros. O recurso de expira\u00e7\u00e3o de transa\u00e7\u00f5es foi bem testado com esse suporte da estrutura.\u00a0\u00a0<\/span><\/p>\n<p><b>Problema 3: gerenciamento de vers\u00f5es:<\/b><span style=\"font-weight: 400\"> Temos que testar diferentes vers\u00f5es de bibliotecas de transa\u00e7\u00f5es e as vers\u00f5es posteriores teriam novos recursos que n\u00e3o est\u00e3o dispon\u00edveis na vers\u00e3o anterior.<\/span> <span style=\"font-weight: 400\">vers\u00e3o. Portanto, a estrutura de teste teve que entender qual recurso n\u00e3o \u00e9 compat\u00edvel e evitar a execu\u00e7\u00e3o desses testes.\u00a0<\/span><\/p>\n<p><b>Resolu\u00e7\u00e3o: <\/b><span style=\"font-weight: 400\">Usamos as extens\u00f5es de execu\u00e7\u00e3o de teste de condi\u00e7\u00e3o do Junit5. Cada conjunto de testes \u00e9 anotado com uma condi\u00e7\u00e3o \"@IgnoreWhen\". Todas as condi\u00e7\u00f5es mencionadas nessa condi\u00e7\u00e3o ser\u00e3o recuperadas e usadas no m\u00e9todo \"ExecuteWhen\" que substitu\u00edmos. Antes de o driver come\u00e7ar a executar qualquer teste, ele entrar\u00e1 em contato com o executor e obter\u00e1 todas as funcionalidades compat\u00edveis com ele. O m\u00e9todo \"ExecuteWhen\" usar\u00e1 as informa\u00e7\u00f5es fornecidas em \"@IgnoreWhen\" e os recursos do executor e decidir\u00e1 se um conjunto de testes precisa ser executado ou ignorado.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Eg3:<\/span><\/p>\n<p><b>Consulte o c\u00f3digo do driver Java: <\/b><a href=\"https:\/\/github.com\/couchbaselabs\/blog-fit-performer\/blob\/main\/driverSupportsVersionManagement.java\"><b>driverSupportsVersionManagement<\/b><\/a><\/p>\n<p><b>Exemplos de funcionalidades testadas: <\/b><span style=\"font-weight: 400\">O SDK que desenvolvesse um recurso um pouco mais tarde do que os outros SDKs poderia usar esse recurso do FIT para ativar esses testes assim que implementasse seu recurso. Isso nos ajudou no desenvolvimento orientado por testes.<\/span><\/p>\n<p><b>Problema 4: V\u00e1rios artistas: <\/b><span style=\"font-weight: 400\">\u00a0<\/span><b>Transa\u00e7\u00f5es paralelas:<\/b><\/p>\n<p><span style=\"font-weight: 400\">As transa\u00e7\u00f5es podem ser executadas em paralelo. As transa\u00e7\u00f5es do Couchbase confirmam o modelo de isolamento.   Ou seja, quando duas ou mais transa\u00e7\u00f5es s\u00e3o executadas no mesmo conjunto de documentos, isso n\u00e3o deve levar a grava\u00e7\u00f5es\/leituras sujas. Para testar isso, se executarmos aleatoriamente \"n\" transa\u00e7\u00f5es em paralelo e, caso isso cause corrup\u00e7\u00e3o de documentos, ser\u00e1 dif\u00edcil saber o que exatamente causou a corrup\u00e7\u00e3o. Cada transa\u00e7\u00e3o pode ter muitas opera\u00e7\u00f5es e cada opera\u00e7\u00e3o teria v\u00e1rios est\u00e1gios. Em que opera\u00e7\u00e3o e em que est\u00e1gio essas transa\u00e7\u00f5es colidiram \u00e9 algo que precisamos saber se precisarmos resolver o problema.<\/span><\/p>\n<p><b>Resolu\u00e7\u00e3o: <\/b><span style=\"font-weight: 400\">Projetamos um mecanismo de travamento em que uma transa\u00e7\u00e3o executa algumas opera\u00e7\u00f5es ou alguns est\u00e1gios em uma opera\u00e7\u00e3o e sinaliza o in\u00edcio da outra transa\u00e7\u00e3o. Essa primeira transa\u00e7\u00e3o aguarda que a segunda seja executada e atinja o est\u00e1gio desejado. Quando a segunda transa\u00e7\u00e3o atinge um determinado est\u00e1gio, ela notifica a primeira transa\u00e7\u00e3o para prosseguir. Isso \u00e9 efetivamente o que acontece at\u00e9 mesmo em transa\u00e7\u00f5es paralelas. Assim, criamos um conjunto de pontos de colis\u00e3o que poderiam levar a conflitos de grava\u00e7\u00e3o-escrita ou leituras sujas e usamos as travas para automatizar esses casos de teste.<\/span><\/p>\n<p><b>Consulte o c\u00f3digo do driver Java: <\/b><a href=\"https:\/\/github.com\/couchbaselabs\/blog-fit-performer\/blob\/main\/driverParallelTransactions.java\"><b>driverParallelTransactions<\/b><\/a><\/p>\n<p><b>C\u00f3digo do motorista:<\/b><\/p>\n<p><b>Exemplos de funcionalidade testada\/bugs encontrados: <\/b><span style=\"font-weight: 400\">As transa\u00e7\u00f5es simult\u00e2neas foram testadas com esse suporte<\/span><\/p>\n<p><b>Problema 5: V\u00e1rios executores:  Transa\u00e7\u00f5es paralelas para diferentes SDKs:<\/b><\/p>\n<p><span style=\"font-weight: 400\">Como oferecemos suporte a transa\u00e7\u00f5es em v\u00e1rios SDKs, a mesma l\u00f3gica pode ser usada ao testar a execu\u00e7\u00e3o paralela de transa\u00e7\u00f5es com SDKs diferentes. Por exemplo: transa\u00e7\u00f5es Java versus transa\u00e7\u00f5es CXX. No exemplo acima, n\u00f3s nos conectamos ao mesmo executor, pois quer\u00edamos executar transa\u00e7\u00f5es paralelas para o mesmo SDK. Nesse caso, o TXN A se conectar\u00e1 ao Executante A (suponha que o Executante A esteja usando transa\u00e7\u00f5es Java) e o Txn B se conectar\u00e1 ao Executante B (executando transa\u00e7\u00f5es CXX)<\/span><\/p>\n<p><b>Consulte o c\u00f3digo do driver Java: <\/b><a href=\"https:\/\/github.com\/couchbaselabs\/blog-fit-performer\/blob\/main\/driverMultiplePerformers.java\"><b>driverMultiplePerformers<\/b><\/a><\/p>\n<p><b>Exemplos de funcionalidade testada\/bugs encontrados: <\/b><span style=\"font-weight: 400\">Transa\u00e7\u00f5es simult\u00e2neas com diferentes clientes SDK foram testadas com esse suporte. Tamb\u00e9m nos ajudou a garantir que os metadados da transa\u00e7\u00e3o estivessem intactos.<\/span><\/p>\n<p><b>Conclus\u00e3o:<\/b><\/p>\n<p><span style=\"font-weight: 400\">Esse projeto arquitet\u00f4nico da estrutura FIT n\u00e3o s\u00f3 nos ajudou a resolver os problemas que nos foram apresentados, mas tamb\u00e9m nos ajudou a automatizar os testes de forma eficiente e a desenvolver a transa\u00e7\u00e3o no modo de desenvolvimento orientado por testes (TDD).\u00a0<\/span><\/p>\n<p><b>Automa\u00e7\u00e3o eficiente de testes<\/b><span style=\"font-weight: 400\">: Dividir a estrutura em um \u00fanico driver e v\u00e1rios executores nos ajudou a desenvolver partes da estrutura de forma independente. O desenvolvedor de cada SDK nos forneceu o executor e o QE p\u00f4de se concentrar na automa\u00e7\u00e3o de testes, ou seja, no driver. Os desenvolvedores tamb\u00e9m puderam adicionar testes de unidade ao driver para que todos os testes de transa\u00e7\u00f5es fossem tratados por essa \u00fanica estrutura.<\/span><\/p>\n<p><b>Desenvolvimento orientado a testes (TDD)<\/b><span style=\"font-weight: 400\">: Depois que o Java SDK foi lan\u00e7ado e o desenvolvimento de outros SDKs de transa\u00e7\u00e3o, ou seja, CXX e dot net, come\u00e7ou, nossa equipe de desenvolvimento teve que desenvolver o aplicativo performer enquanto reutilizava o mesmo aplicativo de driver. Isso os ajudou a desenvolver o SDK de forma TDD.<\/span><\/p>\n<p><span style=\"font-weight: 400\">Esperamos que voc\u00ea tenha gostado deste blog. Estamos adicionando mais recursos a essa estrutura e criaremos um novo blog descrevendo os novos problemas e as novas solu\u00e7\u00f5es. Enquanto isso, para saber mais sobre a estrutura FIT, entre em contato com <\/span><a href=\"mailto:praneeth.bokka@couchbase.com\"><span style=\"font-weight: 400\">praneeth.bokka@couchbase.com<\/span><\/a><span style=\"font-weight: 400\">. Para saber mais sobre as transa\u00e7\u00f5es do Couchbase, visite <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/current\/learn\/data\/transactions.html\"><span style=\"font-weight: 400\">Transa\u00e7\u00f5es do Couchbase<\/span><\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>This blog describes the design and development of the test framework i.e FIT framework for Couchbase transactions in a distributed environment. We&#8217;ll start out by introducing you to high-level architectural insight, then we&#8217;ll walk you through the development of the [&hellip;]<\/p>","protected":false},"author":79214,"featured_media":12394,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1811,1821,1818,2201],"tags":[],"ppma_author":[9481],"class_list":["post-12389","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-couchbase-architecture","category-java","category-tools-sdks"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.8 (Yoast SEO v25.8) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Functional + Integration Testing (FIT) Framework + Design<\/title>\n<meta name=\"description\" content=\"This Couchbase post describes the design and development of the test framework like FIT framework for transactions in a distributed environment.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/pt\/functional-and-integration-testing-fit-framework\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Functional and Integration testing (FIT) Framework\" \/>\n<meta property=\"og:description\" content=\"This Couchbase post describes the design and development of the test framework like FIT framework for transactions in a distributed environment.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/pt\/functional-and-integration-testing-fit-framework\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-11-02T15:00:35+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T04:03:49+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1709\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Praneeth Bokka\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Praneeth Bokka\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/\"},\"author\":{\"name\":\"Praneeth Bokka\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/beab3b1ad6897af1bd7d09aca683201b\"},\"headline\":\"Functional and Integration testing (FIT) Framework\",\"datePublished\":\"2021-11-02T15:00:35+00:00\",\"dateModified\":\"2025-06-14T04:03:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/\"},\"wordCount\":2464,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg\",\"articleSection\":[\".NET\",\"Couchbase Architecture\",\"Java\",\"Tools &amp; SDKs\"],\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/\",\"name\":\"Functional + Integration Testing (FIT) Framework + Design\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg\",\"datePublished\":\"2021-11-02T15:00:35+00:00\",\"dateModified\":\"2025-06-14T04:03:49+00:00\",\"description\":\"This Couchbase post describes the design and development of the test framework like FIT framework for transactions in a distributed environment.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg\",\"width\":2560,\"height\":1709},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Functional and Integration testing (FIT) Framework\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/beab3b1ad6897af1bd7d09aca683201b\",\"name\":\"Praneeth Bokka\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/0b23c9b410f0b7e0c2477863774d6225\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-01-at-3.32.08-PM.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-01-at-3.32.08-PM.png\",\"caption\":\"Praneeth Bokka\"},\"url\":\"https:\/\/www.couchbase.com\/blog\/pt\/author\/praneeth-bokka\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Functional + Integration Testing (FIT) Framework + Design","description":"This Couchbase post describes the design and development of the test framework like FIT framework for transactions in a distributed environment.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/pt\/functional-and-integration-testing-fit-framework\/","og_locale":"pt_BR","og_type":"article","og_title":"Functional and Integration testing (FIT) Framework","og_description":"This Couchbase post describes the design and development of the test framework like FIT framework for transactions in a distributed environment.","og_url":"https:\/\/www.couchbase.com\/blog\/pt\/functional-and-integration-testing-fit-framework\/","og_site_name":"The Couchbase Blog","article_published_time":"2021-11-02T15:00:35+00:00","article_modified_time":"2025-06-14T04:03:49+00:00","og_image":[{"width":2560,"height":1709,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg","type":"image\/jpeg"}],"author":"Praneeth Bokka","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Praneeth Bokka","Est. reading time":"11 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/"},"author":{"name":"Praneeth Bokka","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/beab3b1ad6897af1bd7d09aca683201b"},"headline":"Functional and Integration testing (FIT) Framework","datePublished":"2021-11-02T15:00:35+00:00","dateModified":"2025-06-14T04:03:49+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/"},"wordCount":2464,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg","articleSection":[".NET","Couchbase Architecture","Java","Tools &amp; SDKs"],"inLanguage":"pt-BR","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/","url":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/","name":"Functional + Integration Testing (FIT) Framework + Design","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg","datePublished":"2021-11-02T15:00:35+00:00","dateModified":"2025-06-14T04:03:49+00:00","description":"This Couchbase post describes the design and development of the test framework like FIT framework for transactions in a distributed environment.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/christina-wocintechchat-com-FVgECvTjlBQ-unsplash-scaled.jpg","width":2560,"height":1709},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/functional-and-integration-testing-fit-framework\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Functional and Integration testing (FIT) Framework"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"Blog do Couchbase","description":"Couchbase, o banco de dados NoSQL","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"Blog do Couchbase","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/beab3b1ad6897af1bd7d09aca683201b","name":"Praneeth Bokka","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/0b23c9b410f0b7e0c2477863774d6225","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-01-at-3.32.08-PM.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-01-at-3.32.08-PM.png","caption":"Praneeth Bokka"},"url":"https:\/\/www.couchbase.com\/blog\/pt\/author\/praneeth-bokka\/"}]}},"authors":[{"term_id":9481,"user_id":79214,"is_guest":0,"slug":"praneeth-bokka","display_name":"Praneeth Bokka","avatar_url":{"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-01-at-3.32.08-PM.png","url2x":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2021\/11\/Screen-Shot-2021-11-01-at-3.32.08-PM.png"},"author_category":"","last_name":"Bokka","first_name":"Praneeth","job_title":"","user_url":"","description":""}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/12389","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/users\/79214"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/comments?post=12389"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/posts\/12389\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media\/12394"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/media?parent=12389"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/categories?post=12389"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/tags?post=12389"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/pt\/wp-json\/wp\/v2\/ppma_author?post=12389"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}