Pular para o conteúdo principal

FitNesse - Testes Funcionais no BrERP

TesteFuncionalCompletoFitNesse

Com a ferramenta de testes fitNesse, foi possível a criação de uma série de testes funcionais para a plataforma BrERP, permitindo a automatização de um roteiro de testes das funções mais criticas do sistema. O que proporcionou as equipes de desenvolvimento e implantação uma segurança maior no momento de realizar mudanças e atualizações.

Graças ao FitNesse, foi possível realizar cerca de 450 operações em menos de 30 segundos, retratando os processos descritos na imagem acima, desde a população de dados e configuração do sistema, até a realização de transações de venda nacional e internacional, contanto com Recebimento de Materiais e Fatura, bem como uma Asserção de Valores Esperados, assegurando que tudo está funcionando como deveria.

A organização dos scripts de teste no FitNesse

Os testes no fitNesse são organizados por meio de tabelas, com duas colunas, sendo a da esquerda o campo em que o valor deve ser inserido, e a direita, o valor a ser inserido.

TestColumnsExample

O fitNesse pode utilizar as variáveis de contexto do iDempiere para obter os valores a serem inseridos. Um exemplo disso, é o contido na 3º linha da seleção em laranja: AD_Client['Mundo do Café S/A'].AD_Client_ID. Essa expressão, quando evaluada, retorna o User ID do usuário Mundo do Café S/A.

Além disso, sempre, a primeira linha da tabela, indica ao fitNesse qual ação deve ser executada. As funções que já foram utilizadas e testadas são:

Login

Realiza o Login no sistema com os dados apresentados. Um exemplo é o da imagem acima.

Create Record

Insere um registro na tabela informada, utilizando as classes de sistema. Um exemplo disso pode ser visto na imagem abaixo:

CreateRecordExample

A primeira linha, Create Record indica qual função será executada. Na segunda linha, *Table* indica qual tabela deve ser populada, no caso, M_Shipper. As linhas seguintes indicam quais dados devem ser inseridos. A partir disso, o FitNesse utiliza as Classes de Modelo para inserir os dados, passando por todos os processos de validação do sistema.

Set Variable

Essa função tem como objetivo instanciar uma variável no contexto dos testes. Essa variável pode então, ser utilizada como valor a ser utilizado em outras ações. A variável pode tanto ser instanciada com valores estáticos, outras variáveis de contexto, ou até mesmo, o resultado de querys SQL

SetVariableExampleWithOtherVariable

SetVariableExampleWithSQL

Note que para armazenar o resultado de uma query em uma variável, podemos utilizar outras variáveis na cláusula WHERE. Se a Query retornar mais de um valor, apenas o primeiro será armazenado na variável. Além disso, apenas uma coluna pode ser selecionada.

Update Record

Muito parecida com a função Create Record, esta, tem por sua vez a função de atualizar um registro no sistema. Também é necessário informar uma tabela alvo e também as informações a serem atualizadas. Além, é claro, de informar A condição de Atualização. O famoso "WHERE" do SQL.

UpdateRecordExample

Delete Record

Muito semelhante com a função Update Record, porém, esta por sua vez, remete a função DELETE do SQL, ou seja, apaga um registro da base da dados. Da mesma forma que a Update, é necessário informar uma tabela alvo e a condição WHERE

DeleteRecordExample

Assert Record

Essa função certamente é um dos pontos mais importantes dos testes. Ela é responsável por assegurar que os valores obtidos nas tabelas da base de dados é o mesmo que o esperado.

AssertRecordExample

Note que, na coluna do lado esquerdo, abaixo da célula Read, existem duas células com nome de colunas do banco de dados. O valor dessas colunas será comparado com o valor esperado, contido nas colunas da direita. Se forem iguais, o teste passará com sucesso. Caso contrário, o valor diferente será colorido de vermelho.

Em outras palavras, o bloco Assert Record realiza uma Query no banco de dados, com as cláusulas informadas, e compara seus resultados com os resultados esperados. Na imagem acima, a query executada foi:

SELECT lbr_TaxAmt,
lbr_TaxBaseAmt
FROM lbr_taxline
WHERE lbr_taxline_id = @Tax_Line_ID1@;

A variável @Tax_line_ID1@ será evaluada antes de executar a Query, e então, os valores de lbr_TaxAmt e lbr_TaxBaseAmt serão comparados com os valores esperados.

RollBack

A função de RollBack permite escolher se os dados devem ou não serem salvos no banco de dados, ou em termos mais técnicos, se a Transaction deve ou não ser Commitada.

RollBackExampleRollBack

Quando a opção Rollback é configurada como TRUE, a transaction será abortada, e os dados não serão salvos no banco de dados.

RollBackExampleCommit

Quando a opção Commit é configurada como TRUE, a transaction será efetivada, e os dados serão salvos no banco de dados.

Atenção: Existem casos de operações fora de transação dentro do sistema, nesses casos, é preciso commitar os dados, para poder prosseguir nos testes.

FitRecorder

Os scripts de testes do fitNesse podem ser criados utilizando uma poderosa ferramenta, chamada de fitRecorder. Trata-se de um plugin do projeto iDempiere, que permite a geração de scripts de teste apenas com a operação do sistema. De forma simples, o Fit Recorder grava as ações realizadas no sistema, salvando-as em arquivos .txt, já formatados de forma a serem entendidos pelo fitNesse como Scripts de teste.

Por exemplo, com o fitRecorder ativo em seu usuário, ao efetuar login, um arquivo .txt como esse será gerado em na pasta {workspaceLocation}/log:

LOGIN
!|Login|
|User|superuser @ brerp.com.br|
|Password| |
|AD_Client_ID|@Ref=AD_Client[Name='Mundo do Café S/A'].AD_Client_ID|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|AD_Role_ID|@Ref=AD_Role[Name='Mundo do Café S/A Admin'].AD_Role_ID|
|M_Warehouse_ID|@Ref=M_Warehouse[Name='Armazém Fábrica'].M_Warehouse_ID|
|*Login*|

Note que as colunas da tabela de teste estão demarcadas pelo simbolo |. Essa é a sintaxe de operação do FitNesse, todas as tabelas de teste mostradas anteriores, são em verdade, arquivos .txt formatados em forma de tabelas com o simbolo |. Ou seja, após inserido no fitNesse, esse arquivo de teste assume a forma já mostrada anteriormente:

LoginTestExampleClean

Configurando o FitRecorder

Os primeiros passos para configurar o FitRecorder é se assegurar de que o bundle do FitRecorder foi inserido no server product:

fitRecorderBundleOnServerProduct

Também é importante verificar no OSGI Monitor se o plugin está no estado ACTIVE:

fitRecorderBundleActiveOnOSGIMonitor

Caso não estiver STARTED: Execute o comando start ID APLICACAO

O próximo passo, é a ativação do fitRecorder no ModelValidator. Para acessar o Model Validator, você deve estar conectado com o usuário System.

FitRecorderOnModelValidator

Após ativo, o servidor deve ser reiniciado para que as alterações sejam feitas.

O próximo de ultimo passo é a criação de uma preferência individual de usuário para ativação dos logs. Para isso, conecte-se ao sistema com o usuário que desejar gravar os scripts de teste, e crie uma preferência como a abaixo:

fitRecorderUserPreference

Salva a preferência, os logs começarão a ser armazenados no diretório log, na raiz do workspace.

ATENÇÃO: Cada vez que o usuário com a preferência ativa logar no sistema, um novo arquivo de log será gerado. Isso é muito util para organizar a geração de testes. É uma boa prática deslogar e logar novamente a cada passo do script de teste, deixando cada passo isolado em um único arquivo de log.

Exemplo Prático: A criação de um script de Pedido de Compra

A melhor maneira de compreender o processo de geração de um script de teste pelo fitRecorder, é de fato, criando um script de teste. A criação de um Pedido de Compra é um bom caso de exemplo, pois envolve o cadastro de linhas de pedido, com movimentações fiscais dentro das classes de modelo da LBR.

Lembrando da da orientação sobre isolar os casos de teste em arquivos de logs separados, inicie o caso de teste logando no sistema:

LoginScreen

Atente-se a selecionar o perfil em que a preferência do fitRecorder foi configurada Note que ao logar, na pasta {WorkSpaceRoot}/log, surgirá um arquivo com um nome parecido a: fit_test_5001100EmailUsuario.txt.

LogOnDirectory

Uma vez dentro do sistema, vá até a janela Pedido de Compra e preencha as informações necessárias:

PedidoDeCompraExemplo1

PedidoDeCompraExemplo2

Salvo o Pedido de Compra, crie uma linha de pedido:

LinhaPedidoDeCompra

Agora, configure os impostos do pedido, no caso deste exemplo:

'PIS': 1,65%,
'COFINS': 7,60%,
'ICMS': 18% - CST/CSTON: 10,
'ICMSST': 18% - MVA 40%,
'IPI': 10%

ImpostoBrasileiro

Após salvar a linha de pedido, o conteúdo do arquivo de log do fitRecorder, deve ser algo como isso:

LOGIN
!|Login|
|User|superuser @ brerp.com.br|
|Password| |
|AD_Client_ID|@Ref=AD_Client[Name='Mundo do Café S/A'].AD_Client_ID|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|AD_Role_ID|@Ref=AD_Role[Name='Mundo do Café S/A Admin'].AD_Role_ID|
|M_Warehouse_ID|@Ref=M_Warehouse[Name='Armazém Fábrica'].M_Warehouse_ID|
|*Login*|


CREATE RECORD
!|Create Record||
|*Table*|C_Order|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|AD_User_ID|@Ref=AD_User[Name='PJ dentro do Estado Contribuinte'].AD_User_ID|
|AmountRefunded|0.00|
|AmountTendered|0.00|
|Bill_BPartner_ID|@Ref=C_BPartner[Value='003-23969257000151'].C_BPartner_ID|
|Bill_Location_ID|@Ref=C_BPartner_Location[Name='Cobrança Fatura e Entrega'].C_BPartner_Location_ID|
|Bill_User_ID|@Ref=AD_User[Name='PJ dentro do Estado Contribuinte'].AD_User_ID|
|C_BPartner_ID|@Ref=C_BPartner[Value='003-23969257000151'].C_BPartner_ID|
|C_BPartner_Location_ID|@Ref=C_BPartner_Location[Name='Cobrança Fatura e Entrega'].C_BPartner_Location_ID|
|C_ConversionType_ID|@Ref=C_ConversionType[Value='S'].C_ConversionType_ID|
|C_Currency_ID|297|
|C_DocType_ID|@Ref=C_DocType[Name='** New **'].C_DocType_ID|
|C_DocTypeTarget_ID|@Ref=C_DocType[Name='Pedido de Compra Material Revenda'].C_DocType_ID|
|ChargeAmt|0|
|cof_AfterDelivery|false|
|COF_C_Custody_ID|@Ref=COF_C_Custody[Value='BOL'].COF_C_Custody_ID|
|COF_CriadoPeloImportadorXML|false|
|cof_EstimatedTotalWeight|0|
|cof_ExibirEmRelatorios|true|
|COF_FatorFinanceiro|0|
|cof_FreightAmt|0|
|cof_InsuranceAmt|0|
|cof_isGenerateNFTransp|false|
|cof_IsIndustrialization|false|
|cof_isMarkup|false|
|cof_JurosMensal|1.0|
|cof_LiberarEntregaFutura|false|
|cof_MarkupAverage|0|
|cof_MarkupMinimum|0|
|cof_MarkupReal|0|
|cof_MarkupVariation|0|
|cof_ModFrete|1|
|cof_OtherAmt|0|
|cof_SerieNFEntrada|0|
|COF_SituacaoComercial|PA|
|cof_TempoMedio|0|
|C_PaymentTerm_ID|@Ref=C_PaymentTerm[Value='Á Vista'].C_PaymentTerm_ID|
|DateAcct|2019-01-21 00:00:00.0|
|DateOrdered|2019-01-21 00:00:00.0|
|DatePromised|2019-01-21 00:00:00.0|
|DeliveryRule|A|
|DeliveryViaRule|P|
|DocStatus|DR|
|DocumentNo|800098|
|FreightAmt|0|
|FreightCostRule|I|
|GrandTotal|0|
|InvoiceRule|D|
|IsApproved|false|
|IsCreditApproved|false|
|IsDelivered|false|
|IsDiscountPrinted|false|
|IsDropShip|false|
|IsInvoiced|false|
|IsPayScheduleValid|false|
|IsPrinted|false|
|IsPriviledgedRate|false|
|IsSelected|false|
|IsSelfService|false|
|IsSOTrx|false|
|IsTaxIncluded|true|
|IsTransferred|false|
|lbr_RecalculateTax|false|
|lbr_TransactionType|RES|
|M_PriceList_ID|@Ref=M_PriceList[Name='COMPRA'].M_PriceList_ID|
|M_Warehouse_ID|@Ref=M_Warehouse[Value='1000007'].M_Warehouse_ID|
|pag_vTroco|0|
|PaymentRule|P|
|PriorityRule|5|
|Processed|false|
|SalesRep_ID|@Ref=AD_User[Name='SuperUser'].AD_User_ID|
|SendEMail|false|
|TotalLines|0|
|Volume|0|
|Weight|0|
|*Save*|

CREATE RECORD
!|Create Record||
|*Table*|LBR_Tax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|LBR_TaxLine|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|cof_DesonRate|0|
|cof_DifAmt|0|
|cof_DifRate|0|
|cof_ListAmt|0|
|COF_ModBC_ID|@Ref=COF_ModBC[Value='3'].COF_ModBC_ID|
|cof_MVARate|0|
|cof_OverrideCEnq|false|
|cof_OverrideDesonRate|false|
|cof_OverrideDifRate|false|
|cof_OverrideFormula|false|
|cof_OverrideListAmt|false|
|cof_OverrideModBC|false|
|cof_OverrideMotDeson|false|
|cof_OverrideMVARate|false|
|cof_OverrideTaxBase|false|
|cof_OverrideTaxLM|false|
|cof_OverrideTaxRate|false|
|cof_OverrideTaxStatus|false|
|cof_PrintOnDelivery|false|
|cof_vDespAdu|0|
|IsManual|false|
|IsTaxIncluded|false|
|lbr_TaxAmt|0|
|lbr_TaxBase|0|
|LBR_Tax_ID|5001388|
|LBR_TaxName_ID|@Ref=LBR_TaxName[Name='ICMSPROD'].LBR_TaxName_ID|
|lbr_TaxRate|18.000000000000|
|LBR_TaxStatus_ID|@Ref=LBR_TaxStatus[Name='10'].LBR_TaxStatus_ID|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|LBR_TaxLine|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|cof_DesonRate|0.0|
|cof_DifAmt|0|
|cof_DifRate|0.0|
|cof_ListAmt|0.0|
|cof_MVARate|0.0|
|cof_OverrideCEnq|false|
|cof_OverrideDesonRate|false|
|cof_OverrideDifRate|false|
|cof_OverrideFormula|false|
|cof_OverrideListAmt|false|
|cof_OverrideModBC|false|
|cof_OverrideMotDeson|false|
|cof_OverrideMVARate|false|
|cof_OverrideTaxBase|false|
|cof_OverrideTaxLM|false|
|cof_OverrideTaxRate|true|
|cof_OverrideTaxStatus|true|
|cof_PrintOnDelivery|false|
|cof_vDespAdu|0|
|IsManual|false|
|IsTaxIncluded|false|
|lbr_TaxBase|0.0|
|LBR_Tax_ID|5001388|
|LBR_TaxName_ID|@Ref=LBR_TaxName[Name='PISPROD'].LBR_TaxName_ID|
|lbr_TaxRate|1.65|
|LBR_TaxStatus_ID|@Ref=LBR_TaxStatus[Name='99'].LBR_TaxStatus_ID|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|LBR_TaxLine|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|cof_DesonRate|0.0|
|cof_DifAmt|0|
|cof_DifRate|0.0|
|cof_ListAmt|0.0|
|cof_MVARate|0.0|
|cof_OverrideCEnq|false|
|cof_OverrideDesonRate|false|
|cof_OverrideDifRate|false|
|cof_OverrideFormula|false|
|cof_OverrideListAmt|false|
|cof_OverrideModBC|false|
|cof_OverrideMotDeson|false|
|cof_OverrideMVARate|false|
|cof_OverrideTaxBase|false|
|cof_OverrideTaxLM|false|
|cof_OverrideTaxRate|true|
|cof_OverrideTaxStatus|true|
|cof_PrintOnDelivery|false|
|cof_vDespAdu|0|
|IsManual|false|
|IsTaxIncluded|false|
|lbr_TaxBase|0.0|
|LBR_Tax_ID|5001388|
|LBR_TaxName_ID|@Ref=LBR_TaxName[Name='COFINSPROD'].LBR_TaxName_ID|
|lbr_TaxRate|7.60|
|LBR_TaxStatus_ID|@Ref=LBR_TaxStatus[Name='99'].LBR_TaxStatus_ID|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|LBR_TaxLine|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|cof_DesonRate|0.0|
|cof_DifAmt|0|
|cof_DifRate|0.0|
|cof_ListAmt|0.0|
|cof_MVARate|0.0|
|cof_OverrideCEnq|false|
|cof_OverrideDesonRate|false|
|cof_OverrideDifRate|false|
|cof_OverrideFormula|false|
|cof_OverrideListAmt|false|
|cof_OverrideModBC|false|
|cof_OverrideMotDeson|false|
|cof_OverrideMVARate|false|
|cof_OverrideTaxBase|false|
|cof_OverrideTaxLM|false|
|cof_OverrideTaxRate|true|
|cof_OverrideTaxStatus|true|
|cof_PrintOnDelivery|false|
|cof_vDespAdu|0|
|IsManual|false|
|IsTaxIncluded|false|
|lbr_TaxBase|0.0|
|LBR_Tax_ID|5001388|
|LBR_TaxName_ID|@Ref=LBR_TaxName[Name='IPI'].LBR_TaxName_ID|
|lbr_TaxRate|10.0|
|LBR_TaxStatus_ID|@Ref=LBR_TaxStatus[Name='99'].LBR_TaxStatus_ID|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|LBR_TaxLine|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|cof_DesonRate|0|
|cof_DifAmt|0|
|cof_DifRate|0|
|cof_ListAmt|0.0|
|COF_ModBC_ID|@Ref=COF_ModBC[Value='4'].COF_ModBC_ID|
|cof_MVARate|40.0|
|cof_OverrideCEnq|false|
|cof_OverrideDesonRate|false|
|cof_OverrideDifRate|false|
|cof_OverrideFormula|false|
|cof_OverrideListAmt|false|
|cof_OverrideModBC|false|
|cof_OverrideMotDeson|false|
|cof_OverrideMVARate|false|
|cof_OverrideTaxBase|false|
|cof_OverrideTaxLM|false|
|cof_OverrideTaxRate|false|
|cof_OverrideTaxStatus|false|
|cof_PrintOnDelivery|false|
|cof_vDespAdu|0|
|IsTaxIncluded|false|
|lbr_TaxBase|0.0|
|LBR_Tax_ID|5001388|
|LBR_TaxName_ID|@Ref=LBR_TaxName[Name='ICMSST'].LBR_TaxName_ID|
|lbr_TaxRate|18|
|*Save*|


UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = 5001388 |
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-0,00, COFINSPROD-0,00, IPI-0,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = 5001388 |
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-1,65, COFINSPROD-0,00, IPI-0,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = 5001388 |
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-1,65, COFINSPROD-7,60, IPI-0,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = 5001388 |
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-1,65, COFINSPROD-7,60, IPI-10,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = 5001388 |
| *Update* |
| Description | ICMSPROD-18,00, PISPROD-1,65, COFINSPROD-7,60, IPI-10,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = 5006035 |
| *Update* |
| IsTaxIncluded | true|
| lbr_TaxAmt | 5400.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = 5006036 |
| *Update* |
| IsTaxIncluded | true|
| lbr_TaxAmt | 495.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = 5006037 |
| *Update* |
| IsTaxIncluded | true|
| lbr_TaxAmt | 2280.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = 5006038 |
| *Update* |
| lbr_TaxAmt | 3000.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = 5006039 |
| *Update* |
| lbr_TaxAmt | 3213.00|
| lbr_TaxBaseAmt | 47850.00|

CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - ICMSST'].C_Tax_ID|
|IsTaxIncluded|false|
|Processed|false|
|TaxAmt|3213.00|
|TaxBaseAmt|47850.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - COFINS'].C_Tax_ID|
|IsTaxIncluded|true|
|Processed|false|
|TaxAmt|2280.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - PIS'].C_Tax_ID|
|IsTaxIncluded|true|
|Processed|false|
|TaxAmt|495.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - IPI'].C_Tax_ID|
|IsTaxIncluded|false|
|Processed|false|
|TaxAmt|3000.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - ICMS'].C_Tax_ID|
|IsTaxIncluded|true|
|Processed|false|
|TaxAmt|5400.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderLine|
|A_CapvsExp|Cap|
|A_CreateAsset|false|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_BPartner_ID|@Ref=C_BPartner[Value='003-23969257000151'].C_BPartner_ID|
|C_BPartner_Location_ID|@Ref=C_BPartner_Location[Name='Cobrança Fatura e Entrega'].C_BPartner_Location_ID|
|C_Currency_ID|297|
|cof_EntregaParcial|false|
|cof_EstimatedWeight|0|
|cof_FreightAmt|0|
|cof_InsuranceAmt|0|
|cof_isGenericItem|false|
|COF_Juros|0|
|cof_MarkupBasePrice|0|
|cof_MarkupMaximum|0|
|cof_MarkupMinimum|0|
|cof_MarkupPrice|0|
|cof_OtherAmt|0|
|cof_POReferenceLine|0|
|cof_PrecoBase|0|
|cof_PrecoNegociacao|0|
|COF_QtdAnulada|0|
|cof_QtdEntregaFutura|0|
|cof_RealMargin|0|
|COF_SituacaoComercial|PL|
|cof_TaxRulesHistory| ORG MATRIZ-ICMS CFOPLine [1000170] |
|C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA'].C_Tax_ID|
|C_UOM_ID|@Ref=C_UOM[Name='Cada (Por Unidade)'].C_UOM_ID|
|DateOrdered|2019-01-21 00:00:00.0|
|DatePromised|2019-01-21 00:00:00.0|
|Discount|0.00|
|FreightAmt|0|
|IsDescription|false|
|LBR_CFOP_ID|@Ref=LBR_CFOP[Value='2.102'].LBR_CFOP_ID|
|lbr_RecalculateTax|true|
|LBR_Tax_ID|5001388|
|Line|20|
|LineNetAmt|30000.00|
|M_AttributeSetInstance_ID|0|
|M_Product_ID|@Ref=M_Product[Value='Produto Revenda nacional – ST'].M_Product_ID|
|M_Warehouse_ID|@Ref=M_Warehouse[Value='1000007'].M_Warehouse_ID|
|PriceActual|300.00|
|PriceCost|0|
|PriceEntered|300.00|
|PriceLimit|0|
|PriceList|300|
|Processed|false|
|QtyDelivered|0|
|QtyEntered|100|
|QtyInvoiced|0|
|QtyLostSales|0|
|QtyOrdered|100|
|QtyReserved|0|
|RRAmt|0|
|TaxAmt|0|
|*Save*|

Fica claro agora que o fitRecorder é capaz de gravar as operações em todas as classes de modelo do sistema. Analisando o script de teste, é possível perceber que o sistema segue o seguinte algoritmo para realizar um pedido de compra:

  • Criação de Pedido de Compra na tabela C_Order

  • Criação de Registro na tabela LBR_Tax

  • Criação de Linhas de imposto, baseadas nos impostos descritos na operação. Tabela LBR_TaxLine

  • Atualização da Descrição do imposto na tabela LBR_Tax

  • Atualização do valor dos impostos nas linhas, após o mesmo ter sido calculado. Tabela LBR_TaxLine

  • Criação das taxas de imposto na tabela C_OrderTax

  • Criação da Linha de pedido, na tabela C_OrderLine

Ajustes Dinâmicos

O fitRecorder gera os scripts de teste armazenando os dados exatos da execução. Isso quer dizer que, até mesmo os IDs sequenciais do banco de dados são salvos no teste, o que é um problema caso o objetivo seja fazer testes dinâmicos, que não precisam ter sua transação commitada no banco de dados. Para permitir a execução de testes dinâmicos, deve-se realizar alguns ajustes no script gerado pelo fitRecorder. Trata-se basicamente de substituir IDs fixos por variáveis de contexto, ou armazena-los em variáveis de contexto. Acompanhe o processo de ajuste abaixo:

CREATE RECORD
!|Create Record||
|*Table*|C_Order|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|AD_User_ID|@Ref=AD_User[Name='PJ dentro do Estado Contribuinte'].AD_User_ID|
|AmountRefunded|0.00|
|AmountTendered|0.00|
|Bill_BPartner_ID|@Ref=C_BPartner[Value='003-23969257000151'].C_BPartner_ID|
|Bill_Location_ID|@Ref=C_BPartner_Location[Name='Cobrança Fatura e Entrega'].C_BPartner_Location_ID|
|Bill_User_ID|@Ref=AD_User[Name='PJ dentro do Estado Contribuinte'].AD_User_ID|
|C_BPartner_ID|@Ref=C_BPartner[Value='003-23969257000151'].C_BPartner_ID|
|C_BPartner_Location_ID|@Ref=C_BPartner_Location[Name='Cobrança Fatura e Entrega'].C_BPartner_Location_ID|
|C_ConversionType_ID|@Ref=C_ConversionType[Value='S'].C_ConversionType_ID|
|C_Currency_ID|297|
|C_DocType_ID|@Ref=C_DocType[Name='** New **'].C_DocType_ID|
|C_DocTypeTarget_ID|@Ref=C_DocType[Name='Pedido de Compra Material Revenda'].C_DocType_ID|
|ChargeAmt|0|
|cof_AfterDelivery|false|
|COF_C_Custody_ID|@Ref=COF_C_Custody[Value='BOL'].COF_C_Custody_ID|
|COF_CriadoPeloImportadorXML|false|
|cof_EstimatedTotalWeight|0|
|cof_ExibirEmRelatorios|true|
|COF_FatorFinanceiro|0|
|cof_FreightAmt|0|
|cof_InsuranceAmt|0|
|cof_isGenerateNFTransp|false|
|cof_IsIndustrialization|false|
|cof_isMarkup|false|
|cof_JurosMensal|1.0|
|cof_LiberarEntregaFutura|false|
|cof_MarkupAverage|0|
|cof_MarkupMinimum|0|
|cof_MarkupReal|0|
|cof_MarkupVariation|0|
|cof_ModFrete|1|
|cof_OtherAmt|0|
|cof_SerieNFEntrada|0|
|COF_SituacaoComercial|PA|
|cof_TempoMedio|0|
|C_PaymentTerm_ID|@Ref=C_PaymentTerm[Value='Á Vista'].C_PaymentTerm_ID|
|DateAcct|2019-01-21 00:00:00.0|
|DateOrdered|2019-01-21 00:00:00.0|
|DatePromised|2019-01-21 00:00:00.0|
|DeliveryRule|A|
|DeliveryViaRule|P|
|DocStatus|DR|
|FreightAmt|0|
|FreightCostRule|I|
|GrandTotal|0|
|InvoiceRule|D|
|IsApproved|false|
|IsCreditApproved|false|
|IsDelivered|false|
|IsDiscountPrinted|false|
|IsDropShip|false|
|IsInvoiced|false|
|IsPayScheduleValid|false|
|IsPrinted|false|
|IsPriviledgedRate|false|
|IsSelected|false|
|IsSelfService|false|
|IsSOTrx|false|
|IsTaxIncluded|true|
|IsTransferred|false|
|lbr_RecalculateTax|false|
|lbr_TransactionType|RES|
|M_PriceList_ID|@Ref=M_PriceList[Name='COMPRA'].M_PriceList_ID|
|M_Warehouse_ID|@Ref=M_Warehouse[Value='1000007'].M_Warehouse_ID|
|pag_vTroco|0|
|PaymentRule|P|
|PriorityRule|5|
|Processed|false|
|SalesRep_ID|@Ref=AD_User[Name='SuperUser'].AD_User_ID|
|SendEMail|false|
|TotalLines|0|
|Volume|0|
|Weight|0|
|*Save*|

O primeiro passo é remover a linha |DocumentNo|800098|, pois o ID sequencial será inevitavelmente gerado pelo sistema.

CREATE RECORD
!|Create Record||
|*Table*|LBR_Tax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|LBR_TaxLine|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|cof_DesonRate|0|
|cof_DifAmt|0|
|cof_DifRate|0|
|cof_ListAmt|0|
|COF_ModBC_ID|@Ref=COF_ModBC[Value='3'].COF_ModBC_ID|
|cof_MVARate|0|
|cof_OverrideCEnq|false|
|cof_OverrideDesonRate|false|
|cof_OverrideDifRate|false|
|cof_OverrideFormula|false|
|cof_OverrideListAmt|false|
|cof_OverrideModBC|false|
|cof_OverrideMotDeson|false|
|cof_OverrideMVARate|false|
|cof_OverrideTaxBase|false|
|cof_OverrideTaxLM|false|
|cof_OverrideTaxRate|false|
|cof_OverrideTaxStatus|false|
|cof_PrintOnDelivery|false|
|cof_vDespAdu|0|
|IsManual|false|
|IsTaxIncluded|false|
|lbr_TaxAmt|0|
|lbr_TaxBase|0|
|LBR_Tax_ID|@LBR_Tax.LBR_Tax_ID@|
|LBR_TaxName_ID|@Ref=LBR_TaxName[Name='ICMSPROD'].LBR_TaxName_ID|
|lbr_TaxRate|12.000000000000|
|LBR_TaxStatus_ID|@Ref=LBR_TaxStatus[Name='00'].LBR_TaxStatus_ID|
|*Save*|

Agora, é necessário substituir a linha |LBR_Tax_ID|5001388|, por |LBR_Tax_ID|@LBR_Tax.LBR_Tax_ID@|. A variável de contexto @LBR_Tax.LBR_Tax_ID@ é criada automaticamente pelo fitNesse, e remete ao ID do registro criado na tabela LBR_Tax. Após isso, é preciso armazenar o ID criado na tabela LBR_TaxLine em uma variável, pois o mesmo será utilizado posteriormente no cálculo dos impostos. Para isso, basta adicionar a tabela:

!|Set Variable                              |
|@Tax_Line_id1@|@LBR_TaxLine.LBR_TaxLine_ID@|

O processo deve ser repetido para todas as linhas de imposto criadas.

Agora, o sistema performa diversas atualizações na descrição do registro criado na tabela LBR_Tax. Portanto, é necessário substituir o ID fixo da cláusula where pela variável de contexto @LBR_Tax.LBR_Tax_ID@:

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = @LBR_Tax.LBR_Tax_ID@ |
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-0,00, COFINSPROD-0,00, IPI-0,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = @LBR_Tax.LBR_Tax_ID@|
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-1,65, COFINSPROD-0,00, IPI-0,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = @LBR_Tax.LBR_Tax_ID@|
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-1,65, COFINSPROD-7,60, IPI-0,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = @LBR_Tax.LBR_Tax_ID@ |
| *Update* |
| Description | ICMSPROD-12,00, PISPROD-1,65, COFINSPROD-7,60, IPI-10,00, ICMSST-18,00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_Tax |
| *Where* | LBR_Tax_ID = @LBR_Tax.LBR_Tax_ID@ |
| *Update* |
| Description | ICMSPROD-18,00, PISPROD-1,65, COFINSPROD-7,60, IPI-10,00, ICMSST-18,00|

A próxima parte do processo, é substituir as variáveis criadas nas diversas funções de update realizadas nos registros da tabela LBR_TaxLine:

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = @Tax_Line_id1@|
| *Update* |
| IsTaxIncluded | true|
| lbr_TaxAmt | 5400.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = @Tax_Line_id2@|
| *Update* |
| IsTaxIncluded | true|
| lbr_TaxAmt | 495.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = @Tax_Line_id3@ |
| *Update* |
| IsTaxIncluded | true|
| lbr_TaxAmt | 2280.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = @Tax_Line_id4@ |
| *Update* |
| lbr_TaxAmt | 3000.00|
| lbr_TaxBaseAmt | 30000.00|

UPDATE RECORD
!| Update Record |
| *Table* | LBR_TaxLine |
| *Where* | LBR_TaxLine_ID = @Tax_Line_id5@ |
| *Update* |
| lbr_TaxAmt | 2916.00|
| lbr_TaxBaseAmt | 46200.00|

Agora, vários registros são criados na tabela C_OrderTax. Esses registros precisam ser vinculados com o ID do Pedido de Compra, portanto, é preciso substituir o valor contido na linha |C_Order_ID|@Ref=C_Order[DocumentNo='800098'].C_Order_ID|, pela variável de contexto que armazena o ID do Pedido de Compra, no caso: @C_Order.C_Order_ID@.

CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@C_Order.C_Order_ID@|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - ICMSST'].C_Tax_ID|
|IsTaxIncluded|false|
|Processed|false|
|TaxAmt|2916.00|
|TaxBaseAmt|46200.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@C_Order.C_Order_ID@|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - COFINS'].C_Tax_ID|
|IsTaxIncluded|true|
|Processed|false|
|TaxAmt|2280.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@C_Order.C_Order_ID@|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - PIS'].C_Tax_ID|
|IsTaxIncluded|true|
|Processed|false|
|TaxAmt|495.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@C_Order.C_Order_ID@|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - IPI'].C_Tax_ID|
|IsTaxIncluded|false|
|Processed|false|
|TaxAmt|3000.00|
|TaxBaseAmt|30000.00|
|*Save*|


CREATE RECORD
!|Create Record||
|*Table*|C_OrderTax|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_Order_ID|@C_Order.C_Order_ID@|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA - ICMS'].C_Tax_ID|
|IsTaxIncluded|true|
|Processed|false|
|TaxAmt|5400.00|
|TaxBaseAmt|60000.00|
|*Save*|

O registro na tabela C_OrderLine requer necessariamente um ID de Pedido e um ID de imposto, ou seja, é necessário trocar os valores contidos nas linhas C_Order_ID e LBR_Tax_ID

CREATE RECORD
!|Create Record||
|*Table*|C_OrderLine|
|A_CapvsExp|Cap|
|A_CreateAsset|false|
|AD_Org_ID|@Ref=AD_Org[Name='Filial PR'].AD_Org_ID|
|C_BPartner_ID|@Ref=C_BPartner[Value='003-23969257000151'].C_BPartner_ID|
|C_BPartner_Location_ID|@Ref=C_BPartner_Location[Name='Cobrança Fatura e Entrega'].C_BPartner_Location_ID|
|C_Currency_ID|297|
|cof_EntregaParcial|false|
|cof_EstimatedWeight|0|
|cof_FreightAmt|0|
|cof_InsuranceAmt|0|
|cof_isGenericItem|false|
|COF_Juros|0|
|cof_MarkupBasePrice|0|
|cof_MarkupMaximum|0|
|cof_MarkupMinimum|0|
|cof_MarkupPrice|0|
|cof_OtherAmt|0|
|cof_POReferenceLine|0|
|cof_PrecoBase|0|
|cof_PrecoNegociacao|0|
|COF_QtdAnulada|0|
|cof_QtdEntregaFutura|0|
|cof_RealMargin|0|
|COF_SituacaoComercial|PL|
|cof_TaxRulesHistory| ORG MATRIZ-ICMS CFOPLine [1000170] |
|C_Order_ID|@C_Order.C_Order_ID@|
|C_Tax_ID|@Ref=C_Tax[Name='COMPRA'].C_Tax_ID|
|C_UOM_ID|@Ref=C_UOM[Name='Cada (Por Unidade)'].C_UOM_ID|
|DateOrdered|2019-01-21 00:00:00.0|
|DatePromised|2019-01-21 00:00:00.0|
|Discount|0.00|
|FreightAmt|0|
|IsDescription|false|
|LBR_CFOP_ID|@Ref=LBR_CFOP[Value='2.102'].LBR_CFOP_ID|
|lbr_RecalculateTax|true|
|LBR_Tax_ID|@LBR_Tax.LBR_Tax_ID@|
|Line|20|
|LineNetAmt|30000.00|
|M_AttributeSetInstance_ID|0|
|M_Product_ID|@Ref=M_Product[Value='Produto Revenda nacional – ST'].M_Product_ID|
|M_Warehouse_ID|@Ref=M_Warehouse[Value='1000007'].M_Warehouse_ID|
|PriceActual|300.00|
|PriceCost|0|
|PriceEntered|300.00|
|PriceLimit|0|
|PriceList|300|
|Processed|false|
|QtyDelivered|0|
|QtyEntered|100|
|QtyInvoiced|0|
|QtyLostSales|0|
|QtyOrdered|100|
|QtyReserved|0|
|RRAmt|0|
|TaxAmt|0|
|*Save*|

Por fim, é interessante que um Assert dos valores de imposto seja feito, de forma a garantir que o cálculo de imposto está sendo feito da maneira esperada. Para essa linha de pedido, utilizando esse produto, atrelado a esse CFOP, é esperado que o imposto tenha os seguintes valores:

{
'ICMS' : {
'lbr_TaxAmt': 5400.00,
'lbr_TaxBaseAmt': 30000.00
},
'PIS': {
'lbr_TaxAmt': 495.00,
'lbr_TaxBaseAmt': 30000.00,
},
'COFINS': {
'lbr_TaxAmt': 2280.00,
'lbr_TaxBaseAmt': 30000.00,
},
'IPI': {
'lbr_TaxAmt': 3000.00,
'lbr_TaxBaseAmt':30000.00,
},
'ICMSST':{
'lbr_TaxBase': 2916.00,
'lbr_TaxBaseAmt': 46200.00,
'cof_mvarate': 40,
}
}

Utilizaremos então, a função Assert Record, utilizando as variáveis criadas de linhas de imposto na cláusula where, para assegurar que os valores calculados são os esperados:

!|Assert Record                                |
|*Table* |lbr_taxline |
|*Where* |lbr_taxline_id = @Tax_Line_ID1@|
|*Read* | |
|lbr_TaxAmt |5400.00 |
|lbr_TaxBaseAmt|30000.00 |



!|Assert Record |
|*Table* |lbr_taxline |
|*Where* |lbr_taxline_id=@Tax_Line_ID2@|
|*Read* | |
|lbr_TaxAmt |495.00 |
|lbr_TaxBaseAmt|30000.00 |



!|Assert Record |
|*Table* |lbr_taxline |
|*Where* |lbr_taxline_id=@Tax_Line_ID3@|
|*Read* | |
|lbr_TaxAmt |2280.00 |
|lbr_TaxBaseAmt|30000.00 |



!|Assert Record |
|*Table* |lbr_taxline |
|*Where* |lbr_taxline_id=@Tax_Line_ID4@|
|*Read* | |
|lbr_TaxAmt |3000.00 |
|lbr_TaxBaseAmt|30000.00 |



!|Assert Record |
|*Table* |lbr_taxline |
|*Where* |lbr_taxline_id=@Tax_Line_ID5@|
|*Read* | |
|lbr_TaxAmt |2916.00 |
|lbr_TaxBaseAmt|46200.00 |
|cof_mvarate |40.00 |

Executando o FitNesse pelo Eclipse

O primeiro passo para executar o FitNesse pelo Eclipse é importar o projeto FitNesse no Eclipse. Para isso, dentro do Eclipse, vá para: File -> Import

ImportExistingProject

Na Janela de Importação, selecione a opção Existing Projects into Workspace, dentro da seção General.

ImportExistingProjectFitNesse

Selecione a pasta fitnesse dentro da pasta raiz do projeto e importe-a, clicando no botão Finish.

O próximo passo, é criar uma String de Substituição chamada ADEMPIERE_WEB_PORT, que é usada para indicar ao FitNesse qual a porta em que o servidor do BrERP está rodando. Para isso, digite String no campo Quick Access, e selecione a opção String Substitution

StringSubstitutionSearch

Na Janela de Configuração, selecione o botão New:

StringSubstitution[

É Essencial que o campo Name seja preenchido com ADEMPIERE_WEB_PORT. O campo Value dever ser preenchido com a porta em que o servidor BrERP está rodando.

Uma vez configurada a String de Substituição, vá até o Menu Run Configurations:

RunConfiguration

Dentro do Menu, vá até a seção Java Application e selecione a aplicação iDempiere FitNesse

RunIDempiereFitNesse

A flag -p 6089 indica a porta em que o servidor fitNesse será executado. Clique em Run para iniciar o servidor.

Configurações Iniciais do FitNesse

Após executar o iDempiere FitNesse, a página do fitNesse estará disponível em: http://localhost:6089, ou na porta definida na flag -p.

fitNesseHome

Antes de qualquer coisa, é preciso realizar as configurações iniciais no fitNesse. Para isso, acesse página root, que pode ser encontrada no rodapé da pagina inicial.

FitNesseRootConfiguration

Por definição, o FitNesse tentará encontrar a pasta raiz do projeto, e a configurará na variável classpath. Assegure-se de que ela está correta.

É importante configurar o diretório de sua JAVA_HOME. o FitNesse dever executar a mesma versão Java que o BrERP. Note que em meu caso, configurei o caminho absoluto para o binário java na variável.

Ativando o fitNesse Fixture e fitNesse Server no BrERP

O servidor fitNesse que está hospedado na pagina http://localhost:6089 se comunica pelo BrERP utilizando dois plugins OSGI presentes no projeto, chamados fitNesse Server, que é responsável pela comunicação do fitNesse com o BrERP, e o fitNesse Fixture, que é responsável pelas funções explicadas nesse documento.

Antes de tudo, assegure-se de que os bundles do FitNesse estão selecionados como plugins inclusos no server.product:

fitNesseBundles

Uma vez selecionados, certifique-se de que ambos estão ativos no OSGI Monitor:

fitNesseBundlesActive

Se não estiverem, execute o comando start para ativa-los:

fitNesseBundlesStart

Criação de Testes no FitNesse

Para criar um novo teste no FitNesse, vá até a Suite desejada, no caso a BrERPTestSuite e clique no botão add child:

addChild1

Na janela exibida, selecione o checkbox Tests e insira o nome desejado para o teste. No caso, TesteExemplo. Atenção: Todos os nomes devem ser escritos em Camel Case.

addChild2

Organização de importação de Testes

Para manter os testes organizados, uma boa prática é criar testes modulares e individuais, e importa-los todos em um Conjunto de Testes. Um bom exemplo para isso, é a criação de um teste que é responsável apenas pelo Login no Sistema.

Para isso, crie um novo teste chamado MundoDoCafeLoginTest:

MundoDoCafeLoginTest

Após criado, na tela principal do teste, clique no botão Edit para acessar a Interface de edição de testes.

MundoDoCafeLoginTestEdit

Na interface de edição, insira o Teste de Login mostrado anteriormente, lembrando de completar a senha:

MundoDoCafeLoginTestContent

Dica: O botão Format alinha todos os caracteres | na mesma distância. Ao Clicar em Salvar, o FitNesse mostrará na tela principal do teste a tabela com o conteúdo do Teste de Login.

MundoDoCafeLoginTestScreen

Importação de Testes

Para importar o teste MundoDoCafeLoginTest dentro do Teste Exemplo, basta inserir a linha:

!include -c MundoDoCafeLoginTest

TesteExemploImportLogin

Ao voltar para a tela principal, o FitNesse exibirá o conteúdo do MundoDoCafeLoginTest como Teste Importado:

TesteExemploLoginScreen

Com o teste de Login importado, basta agora inserir o script de teste ajustado dentro do TesteExemplo, através da ferramenta de edição. Ao final, é interessante adicionar a funcionalidade RollBack, para que os dados não sejam commitados no banco de dados.

TesteExemploRollBack

Atenção: Em alguns conjunto de testes, optei por utilizar a função Commit, para salvar os dados no banco de dados. Isso porque, existem alguns processos que não utilizam transações, o que impossibilita a leitura e obtenção de dados que não estão commitados no Banco de Dados.

Testando

Na Tela Principal do Teste, ao clicar no botão Test, o FitNesse realizará todas as ações, a exibirá os resultados nas planilhas. TesteExemploBotaoTeste

Se tudo ocorrer da forma correta, o teste retornará 52 asserções, 0 erros e 0 exceções.

TesteExemploResultado

Erros indicam que alguma asserção não foi bem sucedida, ou que alguma ação não pode ser feita

Exceções Indicam que a ação gerou uma Exceção Java dentro do FitNesse, ou dentro do próprio BrERP, e são muito preocupantes.