Arquitetura de Software e Testes — conceitos e padrões

Classificado em Computação

Escrito em em português com um tamanho de 18,02 KB

Arquitetura de Software e decisões de projeto

Decisões de projeto de arquitetura: projetam a organização de um sistema para satisfazer os requisitos funcionais e não funcionais de um sistema.

Visões da arquitetura

  • Visão lógica: mostra as abstrações; deve ser possível relacionar os requisitos do sistema com as entidades.
  • Visão de processo: mostra o comportamento em tempo de execução; é útil para avaliar características não funcionais como desempenho e disponibilidade.
  • Visão de desenvolvimento: mostra como o software é composto (estrutura de módulos, organização do código).
  • Visão física: mostra o hardware do sistema e como os componentes de software são distribuídos entre processadores.

Padrões e estilos arquiteturais

  • Arquitetura em camadas: permite separação e independência. A funcionalidade do sistema é organizada em camadas separadas; cada camada depende apenas dos recursos e serviços oferecidos pela camada abaixo.
  • Arquitetura repositório: descreve como um conjunto de componentes que interagem compartilha dados; todos os dados são centralizados em um repositório.
  • Arquitetura cliente-servidor: composta por servidores que oferecem serviços, clientes que consomem esses serviços e uma rede de comunicação. Um benefício é a independência entre clientes e servidores, permitindo modificar serviços ou servidores sem alterar o sistema cliente.
  • Arquitetura duto e filtro (pipe-and-filter): o processamento dos dados é organizado de modo que cada componente realiza uma transformação discreta dos dados; os dados fluem através de um pipeline de componentes.
  • Arquitetura de aplicações: arquiteturas de aplicação encapsulam as principais características de uma classe de sistemas.

Projeto orientado a objetos com UML

Um sistema orientado a objetos é composto por objetos interativos que mantêm seu próprio estado local e oferecem operações sobre esse estado. Os objetos incluem os dados e as operações para manipulá-los; portanto, podem ser entendidos e modificados como entidades autônomas.

Diagramas UML

  • Diagrama de atividade: mostra as atividades envolvidas em um processo ou no processamento de dados.
  • Diagrama de casos de uso: mostra as interações entre um sistema e seu ambiente.
  • Diagrama de sequência: mostra as interações entre atores e sistema e entre componentes do sistema ao longo do tempo.
  • Diagrama de classes: mostra as classes de objetos no sistema e as associações entre elas.
  • Diagrama de estado: mostra como o sistema ou um objeto reage a eventos internos e externos.

Modelos estruturais e dinâmicos

Modelos estruturais: exibem a organização de um sistema em termos de seus componentes e seus relacionamentos. Podem ser modelos estáticos que mostram a estrutura do projeto do sistema ou modelos dinâmicos que mostram a organização do sistema quando ele está em execução.

Modelos comportamentais

Modelos comportamentais mostram o que acontece ou deve acontecer quando o sistema responde a um estímulo do seu ambiente. Dois tipos de estímulos:

  • Dados: alguns dados que chegam precisam ser processados pelo sistema.
  • Eventos: alguns eventos disparam o processamento do sistema; podem ter dados associados, mas nem sempre.

Engenharia dirigida a modelos (MDE)

A engenharia dirigida a modelos é uma abordagem de desenvolvimento de software em que os modelos, em vez de programas, são as saídas principais do processo de desenvolvimento. Os programas executados em hardware/software são gerados automaticamente a partir dos modelos. O nível de abstração na engenharia de software é aumentado por meio desse processo; assim, os engenheiros não precisam se preocupar com detalhes de linguagem de programação ou especificidades das plataformas.

Testes, manutenção e reengenharia

Tipos básicos de teste

  • Teste de caixa branca: o analista tem acesso ao código-fonte, conhece a estrutura interna do produto e pode escolher partes específicas de um componente para avaliação. É projetado em função da estrutura do componente e permite uma averiguação precisa do comportamento interno.
  • Teste de caixa preta: o analista não tem acesso ao código-fonte e desconhece a estrutura interna do sistema. Também conhecido como teste funcional, pois é baseado nos requisitos funcionais do software; ele busca falhas que contrariem os requisitos da aplicação.

Manutenção e evolução

O ambiente muda, novos requisitos surgem e o sistema deve ser modificado; caso contrário, começa a ser considerado desatualizado e pode ser substituído por outro mais recente.

Três tipos de manutenção:

  • Correção de defeitos: erros de codificação, requisitos e projeto.
  • Adequação ambiental: quando ocorrem mudanças no hardware, no sistema operacional ou em software de apoio, o sistema deve ser modificado para se adequar a essas mudanças.
  • Adição de funcionalidades: ocorre quando os requisitos do sistema mudam.

Reengenharia de software

A reengenharia é importante em sistemas legados para torná-los mais fáceis de manter. Consiste em melhorar a estrutura e a inteligibilidade, incluindo redocumentação do sistema, refatoração, alteração da arquitetura, mudança de linguagem e outros. Vantagens:

  • Riscos reduzidos: há alto risco em redesenvolver um software essencial; reengenharia reduz esse risco.
  • Custos reduzidos: o custo da reengenharia é significativamente menor do que o de desenvolvimento de novo software.

Deve-se descartar o sistema quando ele não contribui mais efetivamente para os processos de negócio da empresa — por exemplo, quando os processos mudam e o sistema se torna inútil para os novos processos.

Sistemas legados: opções estratégicas: descartar completamente o sistema; desativar e manter com manutenção regular; reestruturar para melhorar a manutenibilidade; substituir parte do sistema por novo.

Objetivos, verificação e validação

Um programa não precisa ser totalmente livre de erros antes de ser entregue: os testes não podem demonstrar que o software é totalmente livre de defeitos nem que se comportará conforme especificado em qualquer situação, pois sempre é possível que um teste esquecido seja o que descobrira problemas importantes.

Testes detectam apenas a presença de erros, não sua ausência: o teste é destinado a mostrar que um programa faz o que é proposto e a descobrir defeitos antes do uso; os resultados verificam erros, anomalias ou atributos não funcionais.

Objetivos dos testes

  • Teste de validação: demonstrar ao desenvolvedor e ao cliente que o software atende aos seus requisitos (estamos construindo o produto certo?).
  • Teste de defeitos: descobrir situações em que o software se comporta de maneira incorreta, indesejável ou diferente das especificações.
  • Verificação: checar se o software atende aos requisitos funcionais e não funcionais (estamos construindo o produto da maneira certa?).
  • Validação: garantir que o software atenda às expectativas do cliente; demonstra o que o software faz e o que o cliente espera.

Inspeção de software (verificação)

  • Durante o teste, erros podem mascarar outros erros; como a inspeção é um processo estático, ela pode descobrir muitos erros sem execução do sistema.
  • Versões incompletas de um sistema podem ser inspecionadas sem custos adicionais; para testes de sistema incompletos seriam necessários dispositivos de teste especializados, aumentando custo.
  • Além de procurar defeitos, uma inspeção pode considerar atributos como qualidade do programa, conformidade com padrões, portabilidade e manutenibilidade, buscando ineficiências, algoritmos inadequados e estilo de programação pobre que dificultem manutenção.
  • Inspeções são mais eficientes que testes de programa para detectar certos tipos de problemas.

Três fases de testes de software

  1. Testes de desenvolvimento: o sistema é testado durante o desenvolvimento para descobrir bugs; projetistas e programadores podem participar.
  2. Testes de release (caixa preta): uma equipe independente testa uma versão completa antes da liberação para usuários, verificando se atende aos requisitos das partes interessadas.
  3. Teste de usuário (aceitação): os usuários testam o sistema em seu próprio ambiente.

Testes de regressão e automatizados

Testes de regressão: reexecução de testes anteriores para verificar se alterações no programa não introduziram novos bugs. Garantem que o programa ainda satisfaz seus requisitos.

Testes automatizados: testes codificados em um programa que é executado cada vez que o sistema em desenvolvimento é testado. Não podem ser totalmente automatizados, pois só verificam se um programa faz aquilo a que se propõe ou se não gera efeitos colaterais indesejados.

Partes de um teste automatizado:

  1. Configuração: inicia-se o sistema com o caso de teste.
  2. Chamada: quando você chama o objeto ou método a ser testado.
  3. Afirmação: compara o resultado da chamada com o resultado esperado.

Testes de desenvolvimento e níveis de teste

Testes de desenvolvimento: responsáveis pelo desenvolvimento de testes e pela manutenção de registros detalhados de resultados, visando descobrir bugs.

  • Teste unitário: unidades individuais de programa ou classes de objetos são testadas isoladamente; testa a funcionalidade de objetos ou métodos.
  • Teste de componentes (integração de unidades): várias unidades individuais são integradas para criar componentes compostos; deve testar as interfaces dos componentes.
  • Teste de sistema: alguns ou todos os componentes do sistema são integrados e o sistema é testado como um todo, verificando a interação entre componentes.

Testes unitários automatizados e frameworks

Unitários automatizados podem usar frameworks como junit para escrever e executar testes. Frameworks de teste unitário fornecem classes de teste genéricas que você pode estender para criar casos específicos; eles executam os testes implementados e informam, geralmente via interface gráfica, o sucesso ou falha. Um conjunto de testes pode ser executado em poucos segundos, permitindo rodar todos os testes a cada alteração no programa.

Escolha de casos de teste unitário

Objetivos dos casos de teste unitário:

  • Mostrar que, quando usado como esperado, o componente faz o que se propõe.
  • Revelar defeitos nos componentes se existirem.

Estratégias:

  • Teste de partição: identificar grupos de entradas com características comuns e escolher testes representativos para cada grupo.
  • Testes baseados em diretrizes: usar diretrizes de teste para escolher casos de teste.

Testes baseados em requisitos, cenário e desempenho

  • Testes baseados em requisitos: o requisito deve ser escrito de modo que um teste possa ser projetado para ele; assim, um testador pode verificar se o requisito foi satisfeito.
  • Teste de cenário: abordagem de teste de release em que você imagina cenários típicos de uso e os usa para desenvolver casos de teste.
  • Teste de desempenho: projetado para assegurar que o sistema possa processar a carga a que se destina.

Teste de usuário e testes de release

Teste de usuário: estágio em que usuários ou clientes fornecem entradas e feedback sobre o sistema. A influência do ambiente de trabalho do usuário afeta confiabilidade, desempenho, usabilidade e robustez — inclui teste beta, teste de aceitação e teste alfa.

Testes de release: têm o objetivo de convencer o fornecedor do sistema de que ele é bom o suficiente para uso, demonstrando que oferece a funcionalidade, desempenho e confiabilidade especificados e que não falhará durante uso normal.

Reiteração: projeto orientado a objetos, objetivos e tipos de teste

Projeto orientado a objetos com UML: um sistema orientado a objetos é composto de objetos interativos que mantêm seu próprio estado local e oferecem operações sobre esse estado.

Dois objetivos distintos dos testes

  • Teste de validação: demonstrar ao desenvolvedor e ao cliente que o software atende aos requisitos.
  • Teste de defeitos: descobrir situações em que o software se comporta incorretamente, de forma indesejável ou diferente das especificações.

Verificação e validação

Verificação: checar se o software foi construído conforme os requisitos funcionais e não funcionais (estamos construindo o produto de maneira certa?).

Validação: garantir que o software atende às expectativas do cliente e às especificações (estamos construindo o produto certo?).

Inspeção e eficiência

Inspeção de software (verificação):

  • Erros podem mascarar outros erros; como a inspeção é estática, ela pode descobrir muitos erros sem execução.
  • Versões incompletas podem ser inspecionadas sem custos adicionais; testes exigiriam dispositivos especializados.
  • A inspeção pode avaliar também qualidade do programa, conformidade com padrões, portabilidade e manutenibilidade.
  • Inspeções são frequentemente mais eficientes que testes dinâmicos para detectar determinados problemas.

Três testes do software (reiterado)

  1. Testes de desenvolvimento: teste durante o desenvolvimento para descobrir bugs; projetos e programadores envolvidos.
  2. Testes de release (caixa preta): equipe independente testa versão completa antes de liberar para usuários.
  3. Teste de usuário (aceitação): usuários testam o sistema em seu próprio ambiente.

Testes de regressão e automatizados (reiterado)

Testes de regressão: reexecução de testes anteriores para verificar se alterações não introduziram novos bugs.

Testes automatizados: codificados em programas que são executados sempre que o sistema é testado. Não podem ser totalmente automatizados; apenas verificam que o programa faz o que se propõe ou detectam efeitos colaterais indesejados.

Processo de teste automatizado (reiterado)

  1. Configuração: inicia o sistema com o caso de teste.
  2. Parte de chamada: quando você chama o objeto ou método a ser testado.
  3. Parte de afirmação: compara o resultado da chamada com o resultado esperado.

Testes de desenvolvimento detalhados (reiterado)

Responsáveis pelo desenvolvimento de testes e manutenção de registros detalhados para descobrir bugs:

  • Teste unitário: unidades individuais ou classes testadas isoladamente.
  • Teste de componentes: varias unidades integradas para criar componentes compostos; foco nas interfaces.
  • Teste de sistema: integração de componentes e teste do sistema como um todo, verificando a interação entre componentes.

Unitários automatizados e frameworks (reiterado)

Frameworks de teste unitário permitem escrever testes que são executados automaticamente e reportam sucesso ou falha, possibilitando execução rápida de todo o conjunto de testes após alterações no código.

Escolhas de casos de teste unitário e estratégias (reiterado)

Objetivos: demonstrar comportamento esperado e revelar defeitos. Estratégias: particionamento de entradas e testes baseados em diretrizes.

Testes baseados em requisitos, cenário, desempenho e usuário (reiterado)

  • Teste baseado em requisitos: requisito escrito de modo que um teste possa ser projetado para ele.
  • Teste de cenário: imaginar cenários típicos de uso para criar casos de teste de release.
  • Teste de desempenho: assegurar que o sistema processe a carga esperada.
  • Teste de usuário: estágio em que usuários dão entradas e feedback; ambiente do usuário influencia confiabilidade, desempenho, usabilidade e robustez (beta, aceitação, alfa).

Testes de release (reiterado)

Objetivo: convencer que o sistema é bom o suficiente para uso, mostrando que oferece funcionalidade, desempenho e confiança especificados e que não falhará em uso normal.

Diferença entre teste de release e teste de sistema

O teste de release deve ser realizado por uma equipe separada que não esteve envolvida no desenvolvimento do sistema. O teste de sistema feito pela equipe de desenvolvimento deve centrar-se em bugs e verificar se o sistema é bom suficiente para uso externo (teste de validação).

Observações finais

O conteúdo acima reorganiza e corrige o texto fornecido, mantendo todos os conceitos originais. Foram aplicadas correções ortográficas, gramaticais e de capitalização, além de formatação que melhora a leitura e a indexação para SEO: uso de títulos, listas e termos-chave relevantes.

Entradas relacionadas: