Testes de Sistemas Concorrentes: Uma abordagem formal Testing Concurrent Systems: A Formal Approach Jan Tretmans – University of Twente Paulo Eduardo e Silva Barbosa Março de 2004 Introdução Ultimamente muita pesquisa foi dedicada à área de métodos formais A prática corrente de checagem de corretude é baseada em uma abordagem mais informal A combinação de testes e métodos formais nem sempre é feita Introdução Pouca gente imagina como uma mão lava a outra As mãos sujas dos testes A mão limpa e matemática dos métodos de verificação formal Introdução As visões estão mudando Pesquisas acadêmicas com testes estão evoluindo e mesmo o verificador mais formal admite que um sistema verificado formalmente ainda deve ser testado Métodos formais são cada vez mais usados, uma especificação formal pode ser benéfica durante um teste, dando-lhe maior suporte Propósitos Discutir como testes podem ser executados baseados em especificações formais Como obter vantagens em termos de precisão, claridade e consistência do processo de testes pela adoção de uma abordagem formal Tópicos da discussão Casamento entre métodos formais e testes A necessidade de ambos Uma especificação formal verificada é um bom ponto de partida para testes Testes formais são um bom ponto de partida para introduzir métodos formais no desenvolvimento de software Estrutura da apresentação Discussão informal sobre testes de software clássicos Apresentação de um framework geral e formal para testes utilizando métodos formais Faz uma discussão mais específica desse framework com o formalismo dos sistemas de transições rotulados Discutimos o suporte ferramental e apresentamos um exemplo de aplicação Discussão de fontes e perspectivas Discussão informal sobre testes de software clássicos Testes de software Apresentação da abordagem clássica A especificação é a base do teste Ordens dos testes Testes podem ser aplicados em diferentes níveis de abstração Teste black-box ou funcional Teste white-box Teste grey-box Fases do processo de testes Geração dos testes Execução dos testes Outras atividades importantes: Gerenciamento Manutenção Automação dos testes Teste é um candidato ideal para automação Ferramentas record and playback Ferramentas de cobertura de código Critérios: Todos os caminhos Todos os statements Todas as combinações de uso Framework para testes formais Framework para testes formais É apresentado um framework para uso de métodos formais em testes de conformidade Testa com relação à sua especificação formal do seu comportamento funcional O mais importante é que liga o mundo informal das implementações, testes e experimentações com o mundo formal das especificações e modelos Conceitos abordados no framework Conformidade Observações e testes Testes de conformidade Suas extensões Conformidade Necessitamos de implementações e especificações As especificações são formais. Universo de especificações é denotado por SPECS Implementações são os sistemas que iremos testar. Denotamos por IUT pertencentes a IMPS IUT conforms-to s expressa que IUT é uma correta implementação da especificação s. Formalmente sobre implementações, uma implementação IUT IMPS pode ser modelado por um objeto formal Iiut MODS Isso é chamado como hipóteses de teste Hipóteses de teste Expressam conformidade por uma relação formal entre modelos de implementações e especificações IUT IMPS é dita correta com relação a s SPECS, IUT conforms-to s, sss Iiut MODS de IUT é imp-relacionado com s: Iiut imp s. Uma relação de implementação imp MODS X SPECS Observações e Testes O comportamento de uma IUT é investigado fazendo experimentos na implementação e observando as suas reações casos de testes e execução de testes Casos de testes e execução de testes Considere casos de testes formalmente pertencentes a um domínio TESTS Requer um procedimento para executar um caso de teste t a uma IUT Denotada por EXEC(t,IUT) O que acontece durante a execução A execução de um teste irá levar em um conjunto de observações, subconjunto de OBS Função de observação: Obs: TESTS X MODS P(OBS) obs(t,Iiut) formalmente modela a execução do teste real EXEC(t,IUT) Hipóteses de Testes Seu significado: Para todas as implementações reais que estamos testando, assume-se que existe um modelo, tal que se colocássemos a IUT e o modelo em black boxes e fizéssemos todos os experimentos possíveis em TESTS, não conseguiríamos distinguir entre a real IUT e o modelo Funções de veredito vt Usualmente interpretamos observações de testes em termos de certo ou errado Vt: P(OBS) {fail, pass} Isso Uma é extendido como uma suíte de testes: implementação falha em uma suíte de testes se ela não passa: Testes de conformidade Envolve saber se uma implementação está conforme respeito a uma relação de implementação imp com sua especificação Uma suíte de testes com essa propriedade é chamada completa Pode distinguir entre as implementações conformes e não-conformes É um requerimento muito forte para Testes práticos Implicações sound Implicações exhaustiveness Mostrar soundness Se a propriedade de completude for provada no nível dos modelos, e se tivermos base que as hipóteses de testes valem, então a conformidade de uma implementação com respeito a sua especificação pode ser decidida por meio de um procedimento de testes Derivação de testes Então, uma atividade importante passa a ser dividir os algoritmos no qual produzem suítes de testes sound e/ou completos de uma especificação dada uma relação de implementação Deve produzir suítes de testes sound para alguma especificação s Extensões Arquitetura de testes: define o ambiente no qual uma implementação é testada Introdução da técnica de cobertura: a cada implementação errônea detectada por uma suíte de testes, é atribuido um valor e depois esses valores são integrados Sistemas de transição rotulados De que consiste Seu formalismo modela comportamento de processos (especificações, implementações e testes) Serve como modelo semântico para várias linguagens formais Sistemas de transição rotulados Os domínios formais SPECS, MODS e TESTS serão agora algum tipo de sistema de transição Sua teoria de testes não serve para testes de conformidade Em vez de começar com uma especificação e encontrar uma suíte de testes, define relações de implementação Exemplo Dada uma classe de testes: Um sistema de transição p é equivalente a um q se algum caso de teste em uma classe leva às mesmas observações com p e q Uma vez que as relações de implementação tenham sido definidas, o teste de conformidade inclui encontrar o algoritmo de derivação de testes em que as suítes de testes possam ser derivadas de uma especificação que sejam sound e tentem ser mínimos Teoria ioco-testing Usa os dois tipos de testes Sua relação de implementação é definida como no slide anterior Derivação de testes a partir de especificações é feito do resultado de um algoritmo de derivação de testes sound ou exaustivo Especificações Utilizamos sistemas de transições rotulados ou alguma linguagem formal com a semântica de sistemas de transições rotulados Devemos conhecer as ações do sistema de transição e deve ser particionado em entradas e saídas (Li e Lu) LTS(L) – sobre ação do alfabeto L SPECS := LTS(Li U Lu) Implementações e seus modelos Implementações são modeladas por uma classe especial de sistemas de transição chamados input-output transition systems (IOTS) IOTS(Li, Lu) classe com entradas Li e saída Lu MODS := IOTS(Li, Lu) IMPS são os programas que podem ser modelados por IOTS Relação de implementação ⊆ IOTS(Li,Lu) X LTS(Li U Lu) Observação de refutação ∉ L TESTS = LTS(L U {}) Enquanto observando um processo, uma transição rotulada com só pode ocorrer se nenhuma outra é possível O observador sabe que o processo não pode executar nenhuma das ações que ele oferece ioco Operador paralelo É o tradicional operador paralelo de sincronização extendido com a regra É chamado refutação em pré-ordem Relação de implementação mais fraca (conf) É uma modificação do teste em pré-ordem restringindo todas as observações para os traces que estão contidos na especificação s Facilita os testes porque deixa de considerar o vasto conjunto complementar Faz apenas o que deve fazer A teoria dos testes canônicos baseia-se nessa abordagem Teste em pré-ordem para autômatos entrada/saída É requisitado que as entradas estejam sempre habilitadas Relação ioco Segue os princípios dos testes em pré-ordem com testes que possam refutar ações na refutação em pré-ordem Entradas estão sempre habilitadas A distinção com o IOA é a restrição dos traces apenas das especificações como em conf Definição semi-formal da relação ioco p after σ é o conjunto de estados onde o sistema de transições p pode após executar o trace σ out(p after σ) é o conjunto de ações de saída após p after σ Um estado p é quiescente se não pode ocorrer ação de saída Uma ação δ, indicando quiescencia deve ocorrer apenas se existe um estado quiescente em p after σ Straces(s) são traces de suspensão da especificação, onde δ vai ocorrer com entradas e saídas normais A relação de implementação escolhida é a ioco: imp := ioco Uma implementação é ioco-correta com respeito a especificação s se i nunca produz uma saída na qual não poderia ser produzida por s na mesma situação, após o mesmo trace de suspensão Então i deve ser apenas quiescente, não produzir saídas se s for também Exemplo 1 Exemplo 1 Dois IOTS com Li = {?but} e Lu{!liq,!choc} not( r1 ioco r2) pois: out(r1 after ?but δ ?but) = {!liq, !choc}, Enquanto out (r2 after ?but δ ?but) = {!choc} Testes TESTS é instanciado também com sistemas de transições, mas adicionamos um rótulo extra θ para detecção de refutação Retringimos testes para sistemas determinísticos com comportamento finito Os estados terminais são pass ou fail Testes Para cada estado não-terminal s de um test case que init(s) = {a} para algum a ∈ Li, ou init = Lu U {θ} init(t) é o conjunto de ações iniciais de t O comportamento de cada test case é descrito por uma árvore finita O rótulo especial θ ∉ L U {δ} será usado para detectar estados quiescentes de uma implementação Normalmente é um tipo de time-out Exemplo 2 Observações São logs de ações, traces sobre L U {θ} OBS := (L U {θ})* Função de observação: Composição sincronizada paralela de t e i terminando em um estado final de t Exemplo 3 Para r1 temos três observações com t do exemplo 2: Vereditos atribuído a um conjunto de observações O OBS é pass se todos os traces em O leva ao estado terminal pass do test case É Exemplo 4 No exemplo 3, como o estado terminal de t para a segunda vez é fail, o veredito de r1 é fail. O veredito de r2 é pass Execução de testes EXEC(t, IUT) deve expressar a semântica expressa por obs(t, Iiut) e estabelece as hipóteses de testes Derivação de testes Algoritmo que especifica a derivação dos test cases de uma especificação de um sistema de transição rotulado para a relação de implementação ioco “;” denota um prefixo de ação “+” denota escolha “” denota escolha generalizada S after a denota o conjunto de estados que podem ser alcançados de algum estado em S via uma ação a Algoritmo derivação de testes ioco Seja s uma especificação com estado inicial s0 S é um conjunto não-vazio de estados com inicialmente S = {s0} Um test case t é obtido de S por um número finito de recursões de uma das três escolhas nãodeterminísticas Algoritmo derivação de testes ioco Sobre o algoritmo uma especificação s LTS(L1 U L2) É provado que este algoritmo produz apenas casos de testes sound (que nunca produzem fail enquanto testando uma implementação iococonforming Formalmente, seja der alguma função satisfazendo o algoritmo não-determinístico, então: Dada Alguma implementação não-conforme pode ser sempre detectada por caso de teste gerado por esse algoritmo Seja Ts o conjunto de todos os casos de testes que podem ser gerados pelo algoritmo de s, então: Exemplo 5 Usando o algoritmo de derivação ioco-test, o caso de teste t da figura 2 pode ser derivado da especificação r2 na figura 1 Isso é consistente com a figura 1 e exemplo 4: R1 not ioco r2, r2 ioco r2 (reflexiva) e vt(obs(t,r1)) = fail e vt(obs(t,r2)) = pass O caso de teste t foi usado para detectar que r1 não é ioco-correct com respeito a r2