Teste de conflitos de Postscript do Jmine

Postscript é o conjunto de informações básicas necessário para o funcionamento de uma aplicação. Geralmente estas informações são armazenadas no banco de dados e podem ser qualquer coisa:

  • Um script
  • Um usuário
  • Uma credencial
  • Etc...

Todas as entradas de Postscript possuem uma Primary Key (PK) e podem ter Natural Key (NK), a escolha da PK e da NK ocorre durante a fase de desenvolvimento, e para evitar conflitos entre estes valores criamos uma estrutura de testes que valida estas informações em tempo de build usando o Gevell como base.

Como funciona

Todos os produtos ou camadas precisam implementar o AbstractPostScriptConflictsTest, uma classe que vai listar todas as entidades mapeadas do sistema em questão e enviar ao Gevell para validação. Caso ocorra algum problema, o Gevell informará e o teste (e consequentemente o build) falhará.

Basicamente, três valores são comparados:

  • O nome completo da entidade, por exemplo: jmine.tec.Script
  • A PK da entidade: 1 ou “TESTE”
  • A NK da entidade, caso ela possua um campo de NK este valor será enviado, caso contrário o toString() do objeto será usado para definir este campo

O Gevell receberá um conjunto de tuplas com estas informações (entidade, pk, nk) e vai verificar conflitos em sua base. Um conflito pode ser definido por:

  • Existe outra entrada para a mesma entidade utilizando a PK fornecida
  • Existe outra entrada para a mesma entidade utilizando a NK fornecida

Caso nenhum conlfito ocorra, o Gevell reservará os valores recebidos e que ainda não estavam cadastrados.

Renomeando Entidades

Um cenário que se mostrou bastante comum é a alteração de NKs, por exemplo, mudar o nome de um script. Este é um cenário consideravelmente sensível, uma vez que o teste precisa aceitar os dois valores:

  • Valor antigo para os builds anteriores à alteração
  • Valor novo para os builds posteriores à alteração

Neste caso, é necessário cadastrar a segunda NK diretamente pelo Gevell, na tela de Entradas de Postscript

Sistemas Monitorados

Usamos diversas camadas nos produtos, a configuração de sistemas monitorados veio para garantir que o teste de conflitos ocorra corretamente mesmo quando as entidades estão vindo de outros subsistemas ou camadas.

Imagine o seguinte cenário: uma entidade chamada Computador na Camada PC, e o Sistema MAPS usa esta camada. Um desenvolvedor cria uma entrada de Computador para a camada PC, com PK 1 e NK “Dell”, e ao mesmo tempo, outro desenvolvedor que está mexendo no Sistema MAPS cria também uma entrada de Computador com a PK 1 e NK “HP”.

Sem a noção de hierarquia entre os sistmas não é possível verificar que há conflitos neste cenário. Essa hierarquia é definida diretamente no Gevell, e os testes de postscript devem enviar a informação sobre qual camada está sendo validada em tempo de execução.

Conflitos de Discriminators

O Hibernate permite mapeamento de entidades usando a estratégia SingleTable, onde uma só tabela é utilizada para guardar os dados de diversas entidades. Um exemplo de entidade SingleTable no Tec é a BackOfficeRequestProperty, as classes filhas determinam tipos de propriedades específicas, cujos valores são armazenados em apenas uma tabela. O uso de discriminator, neste caso permite que o Hibernate determine corretamente o tipo específico da entidade.

Um problema comum em grandes projetos que utilizam este recurso é o conflito de discriminators. Imagine que você vai adicionar um novo tipo de BackOfficeRequestProperty, qual valor de discriminator você deve usar? E como garantir que este valor já não está sendo utilizado em algum sistema monitorado dependente do Tec?

Para resolver isto, utilizamos a mesma infra de conflitos de postscript descrita anteriormente, determinando:

Repare que temos dois cenários que podem ocorrer, no que diz respeito ao discriminator e como definir o nome da entidade:

  • A entidade que define a coluna de discriminator também define o seu valor
  • A entiade apenas define o valor do discriminator, a coluna foi definida em alguma classe pai

Sendo assim, para descobrir qual o próximo valor realmente livre para a entidade BackOfficeRequestProperty, por exemplo, basta procurar no gevell por BackOfficeRequestPropertyDiscriminator e verificar os valores existentes. Note que, apesar de ser extremamente comum valores numéricos, esta não é uma regra geral.

Implementando o Teste de Conflitos

É bem simples, basta criar uma classe de testes que herde de AbstractPostScriptConflictsTest e definir o nome do seu Sistema Monitorado já cadastrado no Gevell.

É importante que o módulo e descritor de banco de dados utilizado englobe todas as entidades definidas no sistema para evitar gaps nos testes. Uma prática comum é criar um módulo chamado “database”, cujo objetivo é testar e rodar o RefDB do projeto, e este módulo ter dependência a todos os outros.

Veja um exemplo: jmine.tec.database.PostscriptConflictTest

public class PostscriptConflictTest extends AbstractPostScriptConflictsTest {

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getMonitoredSystem() {
        return "jMine-Tec";
    }

}