É considerado "má prática" verificar o conteúdo / codificação do arquivo em testes de unidade?


84

Um pouco de contexto: Hoje cedo eu tive que atualizar um código SQL que outro colega meu forneceu e, como é um script bastante grande, ele é armazenado como um arquivo separado (que é lido e executado em tempo de execução). Ao fazer isso, acidentalmente reintroduzi dois bugs que tivemos alguns meses atrás, a saber:

  • Por qualquer motivo, o arquivo ASCII foi codificado em UTF-16 (o colega me enviou o arquivo, o que pode ter causado).
  • Faltavam SETinstruções iniciais no script (necessárias devido a algumas coisas do driver na produção, mas não em uma instalação limpa localmente).

Depois de depurar isso por cerca de uma hora (novamente), decidi escrever alguns testes de unidade para garantir que isso nunca acontecesse novamente (e inclua uma maneira rápida de corrigi-lo na mensagem de asserção para fornecer uma solução fácil para futuros desenvolvedores).

No entanto, quando introduzi esse código, outro colega (que também é o líder da nossa equipe) se aproxima de mim e me diz que não devo fazer essas coisas novamente porque:

"Essas coisas não pertencem a testes de unidade"

"Os testes de unidade devem ser usados ​​apenas para verificar o fluxo do seu código"

Estou em conflito agora, pois ainda acho que o que estou fazendo não está errado, pois esse bug não seria reintroduzido no futuro, no entanto, esse colega trabalha como sênior e, no final do dia, decide o que nós gastamos nosso tempo. O que devo fazer? Estou errado por fazer dessa maneira? É considerado má prática?



35
"Os testes de unidade devem ser usados ​​apenas para verificar o fluxo do seu código ", eu diria que é besteira. Tradicionalmente, eles devem incluir todos os testes necessários para garantir que a "unidade" considerada isoladamente esteja correta. Se você escrever apenas os testes de unidade que são úteis para "verificar o fluxo", o que quer que isso signifique, espero que você também tenha amplos conjuntos de testes separados (escritos pelo departamento de controle de qualidade?).
GBR

8
De qualquer maneira, o problema do seu colega provavelmente é exatamente onde você coloca esses testes. Eu focaria nisso, deixando de lado discussões sobre denominações / guerras sagradas. É possível que esses testes sejam muito lentos para o conjunto ao qual você os adicionou, mas também é perfeitamente possível que seu colega esteja apenas fixado em sua ideia de testes de unidade e esteja criando um problema com um problema inexistente; então é melhor esclarecer primeiro qual é o verdadeiro problema.
GBR

2
A propósito, esses testes parecem algo que você deseja executar sempre que modificar esse arquivo SQL. Aqui, o principal problema pode ser as ferramentas de teste, que podem não suportar um modo de operação "executar apenas se modificado"; que gera problemas reais e concretos, pode valer a pena incluir a funcionalidade "somente se modificada" manualmente com algum kludge apenas para esses testes específicos.
GBR

5
Em vez de testar se o arquivo tem o conteúdo e a codificação corretos, por que não testar se ele funciona ?
user253751

Respostas:


156

Provavelmente, os testes que você escreveu estão mais próximos dos testes de integração ou regressão do que os testes de unidade. Embora a linha possa ser muito confusa e às vezes se transformar em pedantismo sobre o que é ou não um teste de unidade, eu voltaria ao seu colega e perguntaria onde deveriam estar os testes que você escreveu, pois eles agregam valor, garantindo a correção do código.

Eu não focaria muito no que é ou não é um teste de unidade e perceberia que, mesmo que seja um teste de integração, ainda pode haver valor no teste.


Comentários não são para discussão prolongada; esta conversa foi movida para o bate-papo .
Thomas Owens

36

Tecnicamente, não é um teste de unidade e mais uma etapa de validação. A abordagem adequada realmente depende do que seu fluxo de trabalho precisa ser. O líder da sua equipe está correto quanto ao objetivo dos testes de unidade. Meu sentimento é que este é um caso de usar a ferramenta errada para um trabalho que ainda precisa ser feito. Então comece com isso:

Qual é o problema que estou tentando resolver?

Pela descrição, você precisa validar se todos os scripts do banco de dados estão em conformidade com alguns padrões.

Quais ferramentas / processos estão disponíveis para resolver o problema?

A qualidade do código-fonte geralmente é verificada por ferramentas de análise estática . Se você não tiver uma ferramenta de análise estática para validar seu SQL, poderá criar uma ferramenta rápida e suja que executa a verificação de qualquer arquivo SQL passado para ele. Não custa verificar se existem ferramentas de análise estática que podem lidar com os problemas de que você está falando.

Se você fizer parte da sua infraestrutura de construção, como incorporá-la ao Jenkins ou algo parecido, ela poderá ser aplicada a todos os arquivos SQL do seu projeto.

Os testes de unidade resolvem apenas o problema do seu arquivo atual.

Como comunico a necessidade da ferramenta?

Isso é muito fácil, você fala com o líder da sua equipe. Ele pode trabalhar com o proprietário do produto e você para determinar o risco / recompensa de investir nas ferramentas. Se este é provavelmente um problema pontual, as ferramentas provavelmente serão um exagero. Se as ferramentas para detectar os maiores problemas são fáceis, pode valer a pena apenas pela verificação de sanidade.

O líder da sua equipe pode ter algumas idéias que você (ou eu) não considerou, que podem solucionar o problema mais corretamente.


21
Ao discutir custo x risco, seria importante observar que ele já causou perda de tempo devido à reintrodução de bugs resolvidos anteriormente. Isso por si só é um forte argumento para automatizar a verificação. 1
jpmc26

1
@ jpmc26, concordo plenamente. A discussão deve começar com o fato de você ter perdido muitas horas para descobrir o que estava errado, e seus testes de unidade foram sua primeira tentativa de impedir que o restante da equipe perdesse a mesma quantidade de tempo. No entanto, trabalhar com o líder da equipe, que deve responder à gerência e às partes interessadas, geralmente é muito apreciado. Como líder de equipe, quero poder defender as ferramentas / práticas / código que gerenciamos. Se eu visse testes de unidade que não pudessem ser rastreados para requisitos reais, eu também estaria preocupado.
Berin Loritsch

1
@BerinLoritsch Tecnicamente, não é um teste de unidade que eu realmente gostaria de saber sobre qual "técnica" você baseia essa afirmação. Até onde eu sei, não existe uma definição autoritativa única de testes de unidade e todos passaram a ter sua própria idéia do que " eles são ".
315:

2
@gbr Há um acordo informal entre os desenvolvedores de que testes de unidade são testes executados isoladamente de sistemas externos. Eles testam apenas o próprio código, não as interações com arquivos, bancos de dados ou outros serviços externos. A Wikipedia documenta esse entendimento: en.wikipedia.org/wiki/Unit_testing#External_work .
jpmc26

1
@BerinLoritsch Também é possível que todos interpretemos a questão de uma maneira diferente, de qualquer forma, não foi muito detalhada e o autor ainda não retornou a ninguém. De qualquer maneira, não estou muito interessado em discutir mais sobre a classificação desses testes. O importante é se eles devem existir (tenho certeza de que devem) e com que frequência eles são executados (a cada mudança no IDE, a cada confirmação local, a cada envio para o repositório central, a todo momento ...).
Gb #

19

É uma prática recomendada chamar testes que acessam arquivos "Testes de Unidade".

Ele: "Essas coisas não pertencem a testes de unidade"

Você: "Faz sentido, mas não consegui encontrar um lugar melhor para colocá-los. Onde eles pertencem?"

Infelizmente, que tipos de testes existem e como eles são organizados são inteiramente específicos da empresa. Então, você precisará descobrir como sua empresa lida com esses testes.

Se você ainda não tem como executar testes automatizados que não sejam testes de unidade, a abordagem pragmática é marcar os testes de unidade que na verdade não são testes de unidade com um prefixo, até que você tenha o suficiente para começar a descobrir que tipo de testes que você realmente tem / precisa. Depois disso, você pode começar a organizar.


2
É uma prática recomendada chamar testes que acessam arquivos "Testes de Unidade". Aqui, o arquivo que está sendo acessado é o arquivo de origem . Ele será acessado tanto quanto qualquer arquivo de origem (para analisá-lo). O fato de que o teste provavelmente não será realizado no mesmo idioma da "unidade" que está sendo verificada (SQL) o torna pouco ortodoxo, mas não deve influenciar sua classificação como teste de unidade. continua ...
GBR

1
... Na verdade, a codificação correta de um arquivo é um "teste" feito por qualquer compilador toda vez que ele lê um arquivo de origem. Aqui, o problema é que, sendo um arquivo externo interpretado em tempo de execução, os "testes do compilador" não serão executados automaticamente e, portanto, é inteiramente apropriado adicioná-los explicitamente, e acho que pode ser considerado um "teste de unidade" por direito. Fragmento de SQL. E parece razoável incluí-lo no conjunto (potencial) de testes executados a cada modificação do arquivo.
GBR

3
A propósito, o que geralmente é recomendado é acessar arquivos externos quando isso puder ser substituído por uma farsa ou algo assim. E, na maioria das definições, os testes de unidade podem acessar arquivos externos ou o que for, é altamente recomendável, pois pode atrasar bastante as coisas. Uma loja é livre para prescrever que você não pode adicionar testes que acessam arquivos ao conjunto de testes que são executados com mais frequência, mas que não os tornam indignos da designação de "teste de unidade", eles apenas os fazem "não" para ser colocado no conjunto de testes mais frequentes deste projeto ".
GBR

2
@Warbo Ele é uma má prática para acessar os arquivos (em geral), eo (mais importante) razão é que eles não são lentos se envolverem "GBs ler sobre um link NFS esquisito", eles são lentos, se, por exemplo, citando Michael Feathers , eles levam 1/10 de segundo. Isso ocorre porque você deseja executar seus testes com a maior frequência possível, idealmente a cada alteração feita no IDE, e quando você tem muitos deles (como deveria), até 10 segundos de segundo são acumulados em horas. (continua ...)
gbr

1
@ Warbo .. Dito isto, o que importa é o tempo total que eles levam, portanto, se você tiver um projeto muito pequeno, com certeza permanecerá pequeno, poderá ser muito mais tolerante com a velocidade dos testes individuais. E se você realmente não se importa de executá-los com frequência, você é totalmente livre para ligar para um funcionário da OPMROC para pegar e enviar por fax um arquivo de um gabinete. Você também pode optar por ser mais relaxado enquanto ainda tem poucos testes e voltar para acelerá-los quando eles começarem a tomar muito, mas você deve levar em conta que essa é uma dívida que você está acumulando.
GBR

14

Michael Feathers diz isso em seu livro Working Effective With Legacy Code:

Na indústria, as pessoas costumam ir e voltar sobre se testes específicos são testes de unidade. [...] volto às duas qualidades: o teste é rápido? Isso pode nos ajudar a localizar erros rapidamente?

Seu teste ajudará a localizar erros rapidamente e a executar rapidamente? Se sim, faça-o! Se não, então não! É simples assim!

Dito isto, você está trabalhando em um ambiente com outras pessoas e precisa se dar bem com elas. Você pode ter que acabar fazendo do jeito dele, mesmo que não concorde com isso.


É uma boa regra, mas ele pouparia confusão se tivesse escrito " se deseja adicionar testes específicos ao conjunto de testes mais frequentemente executado ", em vez de mexer com o termo "teste de unidade".
Gb #

1
@gbr Se os resultados do teste forem precisos, a única outra coisa importante é a rapidez com que é executado. Se eu tiver 100 testes, cada um com menos de 0,1s, no total, eles serão executados em menos de 10s. Fico feliz em executá-los com freqüência. Se eu tiver 1000 testes, eles levarão 1m40s. É muito longo, não os executarei com frequência, mas os executarei assim que fizer as alterações no grupo menor de 100 testes. Não me importo se é tecnicamente um teste de aceitação ou outra coisa. Se if me ajudar a encontrar erros mais cedo, eu o farei independentemente da semântica. Um teste só fornece valor quando é executado.
CJ Dennis

Eu concordo principalmente (independência é outra coisa muito importante, por exemplo), mas, mesmo assim, teria sido melhor se Michael Feathers não tivesse agravado a confusão sobre o que significa "teste de unidade". Não que ele seja particularmente culpado por essa confusão (e seu livro é excelente, nas partes que eu lembrei até agora). Eu estava fazendo uma observação bem menor, de qualquer maneira.
Gbr1

@gbr Ele não está redefinindo os testes de unidade, está dizendo que esse não deve ser o seu critério de inclusão. Seu critério deve ser útil, e é isso que ele está definindo.
CJ Dennis

Reli essa seção; Não tenho certeza, não está claro para mim se isso deve ser uma (espécie de) definição ou apenas um critério. Mas, na verdade " Isso pode nos ajudar a localizar erros rapidamente " pode muito bem implicar o que ele diz antes, sobre isolamento etc. Então, eu poderia ter feito um barulho por nada (embora a sua resposta só poderia ainda ser mal interpretada)
GBR

10

Escrevi testes semelhantes, ocasionalmente, contra arquivos de código-fonte, arquivos de configuração e assim por diante. Eu não os chamaria de testes unitários porque (a) eles estão acessando o sistema de arquivos e podem não ser ultra-rápidos (b) não me importo se eles são executados em todos os check-in (em vez de noturnos em um Servidor de CI).

Você pode chamá-los de testes de integração; certamente, eles estão mais próximos dessa perspectiva do que os testes de unidade.

Meu próprio termo para eles é testes de recursos . IMHO, eles são totalmente justificados se executados todas as noites em um servidor de IC: há um custo mínimo e, quando usado criteriosamente, agrega claramente valor. Uma definição criteriosa : se o teste está verificando um problema que causou um problema (como a codificação mencionada).


4

Um teste de unidade é sobre testar um método ou 'unidade' de código. Você está testando o menor grupo de lógica e código do seu software.

Mais tarde, quando você ingressar com outras unidades, você executará testes de integração.

Espero que o líder de sua equipe incentive sua iniciativa e deva ter oferecido sugestões alternativas. Você definitivamente tem a ideia certa.

Seu SQL é código como qualquer linguagem de geração mais baixa como C # ou Java e deve ser testado como tal. E verificação e validação pertencem a todos os níveis de teste. Portanto, as instruções de codificação e SET estão incluídas, mas não necessariamente testadas exclusivamente. Coisas gerais, como terminações de linhas ou caixas, geralmente você pode usar apenas um gancho ou recurso SCM.

A melhor prática é fazer testes de regressão para garantir que erros anteriores não sejam reintroduzidos. Geralmente, os testes são criados juntamente com qualquer resolução do bug. Se esses erros não são cobertos por testes de regressão no nível da unidade / integração ou sistema e, em seguida, reintroduzem, é um problema de equipe, um problema de processo, não individual.

O problema é que ... erros de sintaxe, instruções ausentes ou blocos lógicos dentro de uma 'unidade' normalmente não são testados. Você está testando as entradas e saídas da unidade em diferentes combinações, testando as muitas possibilidades que podem ser geradas.

Voltando às instruções SET ausentes - elas ajudam a informar as muitas possibilidades de entrada e saída a serem testadas. Que teste você escreveria que falharia se estivesse faltando algum SET escolhido?


O teste de "unidade de código" é uma abordagem do teste de unidade. Na minha experiência, isso leva a testes frágeis e inchaço maciço (por exemplo, zombaria excessiva). Uma alternativa, e IMHO melhor, uma abordagem ao teste de unidade é a "unidade de funcionalidade". Não importa se alguma funcionalidade (por exemplo, "definir um cookie quando conectado") requer um método ou uma dúzia de processos de intercomunicação, ainda é uma unidade.
Warbo 1/11

@ Warbo - Eu chamaria isso de mais próximo (mas não) do teste de integração. O teste de unidade não requer nada excessivo ou maciço. Os testes de unidade devem ser pequenos e rápidos. Na verdade, testar por funcionalidade leva ao que você descreve. Os testes frágeis são aqueles que são 1. maiores ou fazem mais do que deveriam. 2. altamente acoplado 3. não tem uma única responsabilidade.
Ross

3

Se você possui arquivos que se tornam parte do seu produto, o conteúdo deles deve estar correto. Não há razão para você não verificar isso. Por exemplo, se você precisar de seis imagens 1024x 1024 em alguma pasta, faça um teste de unidade que verifique se você tem exatamente isso.

Mas você provavelmente não possui apenas os arquivos, também possui algum código que os lê. Você pode escrever um teste de unidade para esse código. No exemplo acima, a função de ler uma das seis imagens retorna uma imagem de 1024 x 1024 na memória (ou o que ela deveria produzir).

De qualquer forma, pode não ser um teste de unidade, mas é um teste útil. E se você usa uma estrutura de teste de unidade que permite fazer um teste útil (que não é um teste de unidade), por que não usar a estrutura de teste de unidade?


2

Talvez eu esteja entendendo mal o seu problema, mas para mim isso parece um problema que não precisa ser capturado por nenhum tipo de teste dedicado, mas simplesmente pelo sistema de controle de versão . Qualquer alteração em uma base de código deve ser revisada patch a patch antes de confirmar. Uma maneira simples de fazer isso no git é adicionar as alterações com

git add -p

Para cada alteração em um arquivo de texto, o diretório de trabalho perguntará se você realmente deseja mantê-lo. Isso permitiria ver, por exemplo, a exclusão dessas " SETdeclarações iniciais ".

Caso a codificação de um arquivo inteiro seja alterada, algo diferente aconteceria: o algoritmo falharia em diferenciar o arquivo antigo e o novo e, portanto git add -p, não acrescentaria nada. Isso seria visível no outro comando que eu faria antes de qualquer confirmação, a saber

git status

Aqui você veria o arquivo destacado em vermelho, indicando que não são mudanças. Investigar por que eles não entraram git add -prapidamente tornaria o problema óbvio.


ore diga, como isso ajuda qualquer desenvolvedor futuro a evitar exatamente o mesmo problema? ... a coisa sobre testes automatizados (também válidos sobre asserções e design por contrato) é que eles são, bem, erm, automatizados .
precisa saber é o seguinte

O @vaxquis evita exatamente o mesmo problema - embora por coincidência, como efeito colateral de um fluxo de trabalho que seja uma boa ideia por diferentes razões. O que quero dizer é que esse problema poderia acontecer em todos os shows que a equipe do OP não fez muito bom uso de seus VCS. - Nada contra testes automatizados, mas seu valor é testar propriedades semânticas que podem ser interrompidas por alterações inócuas na lógica do programa. Não é para verificar todas as maneiras estúpidas possíveis pelas quais o código-fonte pode mudar.
usar o seguinte código

pela sua lógica, não precisamos de cintos de segurança; só precisamos dirigir com mais cuidado e causar menos acidentes ... Você perdeu o ponto principal do OP levantado - o de um erro humano . Nenhuma quantidade de VCS pode protegê-lo disso . Além disso, FWIW: se um teste pode ser automatizado, deve ser automatizado. Os seres humanos são sempre os elos mais fracos nos processos de engenharia. gité o melhor exemplo disso - uma ótima ferramenta, mas quase inutilizável para meros mortais .
precisa saber é o seguinte

@vaxquis Não, não! Os cintos de segurança são análogos aos tipos de testes que fazem sentido: eles capturam uma grande variedade de situações que provavelmente ocorrerão por acidente. Um teste de codificação de arquivos seria análogo a um robô que o segue e evita que você se asfixie enfiando feijões no nariz.
usar o seguinte código

De acordo com o OP, os arquivos no formato errado já aconteceram duas vezes , então, aparentemente, é provável que ocorram por acidente.
precisa saber é o seguinte

1

Outro ângulo a considerar: como essas duas condições são requisitos para a execução do seu programa, você não deve incorporar a lógica próxima à lógica de execução? Quero dizer: você testa a existência de um arquivo antes de lê-lo e / ou valida seu conteúdo, certo? então como isso é diferente? Eu acho que, como esse é um recurso externo ao código, ele deve ser validado em tempo de execução, antes de ser realmente usado. Resultado: aplicativo mais forte, sem necessidade de escrever testes adicionais.


1
Como a falha apenas no tempo de execução o torna um aplicativo mais forte? Claro, pode ser apropriado também ter verificações de tempo de execução próximas à origem do problema, mas se você pode detectar erros antes que eles causem problemas de tempo de execução, é muito melhor, não acha? Tem certeza de que está familiarizado com o teste automático?
Gbr-

1
"Como a falha apenas no tempo de execução o torna um aplicativo mais forte?" Lance uma exceção se a verificação falhar. No seu teste, verifique se a seção do código que está sendo testado retorna o resultado esperado: isso remove a carga para verificar mais um motivo da falha.
Dr. Gianluigi Zane Zanettini

1
Sua estratégia (quase) nada tem a ver com testes de unidade e testes automatizados em geral, é uma coisa diferente, com diferentes usos.
Gbr #

1
Eu ia sugerir isso. O bug é um detalhe de implementação; Eu imagino que as respostas seriam muito diferentes se a codificação desonesta estivesse em um campo privado, e não em um arquivo independente! Parece que o OP tem 2 problemas: os arquivos de recursos podem estar mal codificados e a produção se comporta de maneira diferente do dev. Verificando o arquivo em tempo de execução, imediatamente antes de ser usado, resolvemos o segundo problema: dev e prod lançam o mesmo erro. Os testes de unidade podem se concentrar na funcionalidade real, e não nos detalhes da implementação; essas verificações "internas" serão exercidas como métodos particulares.
Warbo 1/11

1
@ Dr.GianluigiZaneZanettini Bah ... Eu desisto ... Na minha opinião, na melhor das hipóteses, sua resposta, depois de seus "esclarecimentos" nos comentários, estava fora do tópico (não é uma resposta à pergunta), mas, na realidade, como está, está completamente errado! não há necessidade de escrever testes adicionais ??? Não tenho reputação suficiente para diminuir o voto, mas considere como se tivesse feito isso. E acho que não há muito valor em continuar essa conversa.
GBR

1

Os testes são do mesmo código que qualquer outro e, se suficientemente complexo, também se beneficiam com ... testes de unidade. Parece mais simples adicionar essas verificações de pré-condição diretamente no teste.

A maioria dos testes é simples o suficiente para não exigir isso, mas se alguns forem suficientemente complexos, não vejo nada de fundamentalmente errado com essas verificações de pré-condição. Obviamente, o teste também deve falhar sem eles, mas um bom teste de unidade também informa qual unidade está falhando.

Um script usado como parte do teste e deve ter determinado conteúdo e codificação provavelmente é uma unidade. Pode ter muito mais código e lógica do que o restante do teste. Um teste com esse script não é o melhor design de todos os tempos e, se possível, deve ser refatorado para algo mais direto (a menos que seja um teste de integração).


1
o autor não diz em qualquer lugar que esse script SQL é uma parte de algum teste, você parece ter interpretado mal a pergunta
GBR

Lá difícil de entender, eu assumo que o script SQL faz parte do teste.
H22

seu comentário "Não é difícil de entender" ...
gbr

Difícil de entender. Votação negativa da pergunta.
h22 03/11/19

1

Em primeiro lugar - um dos objetivos dos testes é impedir a ocorrência de problemas no seu código -, portanto, você deve continuar escrevendo testes dessa natureza.

Em segundo lugar - nomear é difícil. Sim, esses claramente não são "testes de unidade", mas podem ser partes desejáveis ​​e necessárias do processo de compilação, porque protegem você de erros óbvios e porque fornecem feedback sobre erros mais cedo (principalmente se você não vê o conseqüências em uma caixa de desenvolvimento).

Portanto, a questão é realmente (deve estar no seu contexto) mais sobre quando e como esses testes são executados do que o que são.

Eu usei esse tipo de teste extensivamente no passado - eles nos salvaram uma boa dose de dor.


E se alguém se importasse em explicar o voto negativo, eu apreciaria isso
Murph

1

Os testes de unidade são sobre executar uma unidade de código isoladamente para confirmar que está produzindo o resultado correto para a entrada correta. O isolamento deve tornar a unidade em teste e o próprio teste repetível, ou seja, não deve depender ou apresentar efeitos colaterais.

O SQL não é exatamente algo que pode ser testado isoladamente; portanto, qualquer teste do SQL não é exatamente um teste de unidade e, exceto pelas instruções SELECT, é quase certo que tenha um efeito colateral. Podemos chamá-lo de teste de integração em vez de teste de unidade.

É sempre aconselhável garantir que qualquer defeito que possa ser introduzido possa ser detectado o mais cedo possível no ciclo de desenvolvimento, e é benéfico fazê-lo de uma maneira que facilite a identificação da origem do defeito para que ele possa ser rapidamente detectado. corrigido.

Os testes em questão podem ser realocados mais apropriadamente fora do corpo dos "testes de unidade" e colocados em outro lugar, mas não devem ser removidos por completo se estiverem fazendo algo útil, como proteção contra a possível introdução de um defeito que pode levar horas para rastrear baixa.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.