Testes em Haskell com a framework HUnit 1.0

Documentos relacionados
Testes de Programas em Haskell

Pedro Vasconcelos DCC/FCUP. Programação Funcional 3 a Aula Definição de funções

Introdução à Programação uma Abordagem Funcional

Conceitos de Linguagens de Programação

Tipos Algébricos. Programação Funcional. Capítulo 11. José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto

Layout. Módulos. Normalmente, cada módulo está armazenado num ficheiro com o mesmo nome do módulo. Exemplo.hs

Linguagem Haskell. Universidade Estadual Santa Cruz Conceitos de Linguagens de Programação. Tiago Carneiro 19 Agosto 2013

Pedro Vasconcelos DCC/FCUP. Programação Funcional 5 a Aula Definições recursivas

Pedro Vasconcelos DCC/FCUP. Programação Funcional 13 a Aula Definição de tipos

Orientação a Objetos e Java

Computação L2. Linguagem C++ Observação: Material Baseado na Disciplina Computação Eletrônica.

Paradigmas de Programação. Java First-Tier: Aplicações. Orientação a Objetos em Java (I) Nomenclatura. Paradigma OO. Nomenclatura

Linguagens de Programação. Programação Funcional e Haskell Programação Interativa Thiago Alves

RESULUÇÃO DOS EXERCÍCIOS E INSTRUÇÕES DE DECISÃO (if{} e else{}) Profº André Aparecido da Silva Disponível em:

Ederson Luiz da Silva Ciência da Computação. Algoritmos e Programação

Linguagens de Programação. Programação Funcional. Carlos Bazilio

Aula Prática 3. Paradigmas da Programação I / Programação Funcional. ESI/MCC 1 o ano (2005/2006)

Programação Funcional

Linguagens de Programação Aula 13

Programação Funcional em Haskell

Programação Funcional Aulas 9, 10 & 11

Sintaxe do Pascal Simplificado Estendido de 12 novas construções em Notação EBNF (BNF estendida)

Pedro Vasconcelos DCC/FCUP. Programação Funcional 2 a Aula Tipos e classes

Programação de Computadores II

TÉCNICO DE INFORMÁTICA - SISTEMAS

Linguagens de Programação Conceitos e Técnicas. Amarrações

Paradigmas de Linguagens de Programação. Expressões e Instruções de Atribuição

Lógica de Hoare. Abordagem que usaremos: aplicar o método de Hoare sobre uma linguagem de programação imperativa simplificada.

Introdução à Programação em C (I)

Sintaxe da linguagem Java

Programação de Computadores:

Arquitetura Von Neumann Dados e instruções são obtidos da mesma forma, simplificando o desenho do microprocessador;

Programação Funcional Aulas 5 & 6

Lição 4 Fundamentos da programação

Programação de Computadores III

Métricas. Métricas. [Engenharia de Software II] Adriano J. Holanda 11/9/2017

Um algoritmo deve conter passos não ambíguos, executáveis e que sejam terminados quando seguidos.

Conceitos de Linguagem de Programação - 2

Programação de Computadores III

Programação I Aula 17 Correção de programas Pedro Vasconcelos DCC/FCUP

Aula Prática 2. Paradigmas da Programação I / Programação Funcional

Universidade de Mogi das Cruzes Implementação Orientada a Objetos - Profª. Danielle Martin. Guia da Sintaxe do Java

Linguagem Funcional Haskell

Capítulo 8. Estruturas de Controle no Nível de Sentença

Pascal. -Cabeçalho do programa. - label - const - type - var - procedure - function. - integer - real - byte - boolean - char - string

Programação Funcional. Capítulo 21. Parsers. José Romildo Malaquias. Departamento de Computação Universidade Federal de Ouro Preto 2018.

Introdução à Programação em C Input / Output

1.2 OPERAÇÕES BÁSICAS EM ALGORITMOS E PROGRAMAS 18

Linguagens de Programação Programação Funcional (Haskell)

Análise de Programação

Preparatório OBI. Prof. André Gustavo Duarte de Almeida docente.ifrn.edu.br/andrealmeida. Aula 01 Introdução a C++

Teoria da Computação e Algoritmos. Introdução à Linguagem Pascal. ALGORITMO <Nome do algoritmo>; <definições>; INÍCIO <Comandos>; FIM.

Programação Orientada a Objetos

Módulo Lógica Programação com aplicações em Java. Projeto khouse Profissionalizante Profª Larissa Brandão

AULA TEÓRICA 3 Tema 2. Introdução a programação em Java (JVM, JDK)

Diagramas Sintáticos

4. Constantes. Constantes pré-definidas

Pedro Vasconcelos DCC/FCUP. Programação Funcional 2 a Aula Tipos e classes

Programação em C. Variáveis e Expressões. Universidade Federal do Rio Grande do Norte Departamento de Engenharia de Computação e Automação

SQL Pacotes. Profa. Dra. Cristina Dutra de Aguiar Ciferri. Laboratório de Bases de Dados Pacotes

Fundamentos da Programação

Linguagem Java - Introdução

Linguagens de Programação I

Linguagem C. Brian W. Kernighan, Dennis Ritchie (K&R) Slides adaptados, inspirados, muitos copiados dos slides do professor Pedro Pereira

Interpretação e Compilação de Linguagens de Programação Semântica CALCI com Ambiente

Algoritmos e Introdução à Programação. Lógica e Linguagem de Programação

Material III-Bimestre Introdução e conceitos fundamentais da Linguagem C#

Conceitos básicos de programação

Programação com Acesso a BD. Programação com OO Acesso em Java

CAP. VI ANÁLISE SEMÂNTICA

Linguagem Haskell. Riocemar S. de Santana

Aula prática 14. Expressão Lambda

Linguagens de Programação Aula 14

Programação Estruturada e Orientada a Objetos

Lambda Cálculo e Programação Funcional. Programação Funcional Bacharelado em Sistemas de Informação Maio

Trabalhos de Laboratório de Interpretação e Compilação de Linguagens de Programação

Expressões Lambda. Programação Funcional. Capítulo 7. José Romildo Malaquias Departamento de Computação Universidade Federal de Ouro Preto

Transcrição:

Teste de programas em Haskell com a framework HUnit 1.0 Pedro Strecht Mestrado em Engenharia Informática 3 de Maio de 2005 1 Testes em Haskell com HUnit 1.0 Breve introdução à linguagem Haskell Apresentação da aplicação em teste Estudo da framework HUnit 1.0 Arquitectura do ambiente de testes Demonstração de testes 2

A linguagem Haskell Linguagem funcional criada em 1990 Motivação: tornar o processo de escrita e manutenção de grandes sistemas de software mais simples e económico. Bom poder expressivo na formulação de algoritmos Outras linguagens funcionais: Lisp, Scheme, ML, Erlang Outras quase funcionais: SQL e XSL 3 Exemplo de utilização Implementação do algoritmo quicksort C qsort( a, lo, hi ) int a[], hi, lo; { int h, l, p, t; if (lo < hi) { l = lo; h = hi; p = a[hi]; do { while ((l < h) && (a[l] <= p)) l = l+1; while ((h > l) && (a[h] >= p)) h = h-1; if (l < h) { t = a[l]; a[l] = a[h]; a[h] = t; } } while (l < h); t = a[l]; a[l] = a[hi]; a[hi] = t; qsort( a, lo, l-1 ); qsort( a, l+1, hi ); } } Haskell qsort [] = [] qsort (x:xs) = qsort lt ++ [x] ++ qsort ge where lt = [y y <- xs, y < x] ge = [y y <- xs, y >= x] 4

Principais características do Haskell Concisão Facilidade de compreensão Forte sistema de tipos Avaliação lazy Abstracção poderosa Gestão automática de memória 5 Tipos e estruturas em Haskell Tipos primitivos: Números: Int, Float, Double Caracteres: Char Booleano: Bool Tipos compostos: Tuplos: (Int, Float, String) (42, 3.14, Hello World! ) Listas: [Int] [1, 2, 3], [Char] Hello World! Bindings (não são atribuições): let y = x + 2 x = 5 in x/y Estruturas condicionais (if-then-else, case): if a == b then a else b Não existem estruturas de ciclo recursividade 6

Funções em Haskell Definição única: add :: Int -> Int -> Int add x y = x + y Definição com padrões: sum :: [Int] -> Int sum [] = 0 sum (x:xs) = x + sum xs Definição com padrões e guardas: abs :: Integer -> Integer abs 0 = 0 abs x x > 0 = x x < 0 = -x 7 Haskell Existem mais algumas construções (mas não são muitas) Estão continuamente em desenvolvimento novas extensões à linguagem Bibliotecas e Frameworks Site oficial: http://www.haskell.org 8

Aplicação em teste Aplicação de simplificação e derivação de expressões matemáticas O objectivo da aplicação é solicitar uma expressão ao utilizador e calcular a expressão simplificada e a sua derivada Desenvolvimento em Haskell A sintaxe das expressões matemáticas é próxima da notação algébrica Suporte de vários operadores algébricos e funções matemáticas Validação sintáctica e semântica de expressões 9 Gramática das expressões EBNF Exemplos 10

Arquitectura da aplicação 11 Framework de testes HUnit 1.0 HUnit - Haskell Unit Testing Framework de testes unitários para Haskell inspirada no JUnit para Java Desenvolvida em 2002 por Dean Harington, encontrando-se ainda na versão 1.0 Simplicidade na criação de testes, agrupamento e execução de grandes colecções de testes Inclui um controlador baseado em texto Facilidade de extensão e costumização Site oficial: http://hunit.sourceforge.net 12

Asserções Uma asserção é o bloco mais básico para a construção de um teste Define-se como sendo a afirmação de que uma proposição é verdadeira No contexto de linguagens de programação equivale a uma condição Existe um tipo de dados específico para as representar: type Assertion = IO () Lançamento de excepção na presença de um erro: assertfailure :: String -> Assertion assertfailure msg = ioerror(usererror ("HUnit:" ++ msg)) Três tipos de asserções: Booleana: Afirma que uma expressão booleana é verdadeira; String: Afirma que uma string é nula; Igualdade: Afirma que duas expressões são iguais. 13 Asserções Asserções booleanas: assercao1 = assertbool "isnumber 2.5" (isnumber "2.5") assercao2 = assertbool "isnumber 2a5" (isnumber "2a5") Asserções de string: assercao1 = assertstring (substr "2x+3" 0 0) assercao2 = assertstring (substr "2x+3" 1 3) Asserções de igualdade: assercao1 = assertequal "Simplificação: 2x+1+3x+4" "5x+5" (simplif "2x+1+3x+4") assercao2 = assertequal "Simplificação: 2x+1+3x+4" "8x-2" (simplif "2x+1+3x+4") Os três tipos retornam um valor de tipo Assertion Podem associar-se identificadores por binding 14

Casos de teste Um caso de teste é um conjunto de uma ou mais asserções Criados com a função TestCase TestCase :: Assertion -> Test Associação a identificador por binding Criação através de identificador de asserção ou com asserção indicada no testes: cteste1 = TestCase assercao1 cteste2 = TestCase (assertstring (substr "2x+3" 1 3)) Caso de teste com duas asserções: cteste = TestCase (do assertequal ("fmt_int: "++expressao) esperado fmt_int assertequal ("fmt_ext: "++expressao) expressao fmt_ext) where expressao = "3x^2-3x+4" esperado = "3*x^2+-3*x+4" fmt_int = ext2int expressao fmt_ext = int2ext fmt_int 15 Agrupamento de testes Um teste é um conjunto de casos de teste Existe um tipo de dados específico para os representar, que é o mesmo do casos de teste: data Test = TestCase Assertion TestList [Test] TestLabel String Test Exemplo na aplicação em teste: tsnumeros = TestCase (assertequal "Simplificacao:" "9" (simplif "2+7")) tsmonomios = TestCase (assertequal "Simplificacao:" "9x" (simplif "2x+7x")) tspolinomio = TestCase (assertequal "Simplificacao:" "12x^2+4x+5" (simplif "3x^2+9x^2+3x+5+x")) tsomas = TestLabel "Somas" (TestList [TestLabel "Numeros" tsnumeros, TestLabel "Monomios" tsmonomios, TestLabel "Polinomio" tspolinomio]) tpnumeros = TestCase (assertequal "Simplificacao:" "14" (simplif "2*7")) tpmonomios = TestCase (assertequal "Simplificacao:" "14x^2" (simplif "2x*7x")) tppolinomio = TestCase (assertequal "Simplificacao:" "405x^6" (simplif "3x^2*9x^2*3x*5*x")) tprod = TestLabel "Produtos" (TestList [TestLabel "Numeros" tpnumeros, TestLabel "Monomios" tpmonomios, TestLabel "Polinomio" tppolinomio]) suitetp = TestLabel "Polinómios" (TestList [tsomas, tprod]) 16

Agrupamento de testes Árvore de testes 17 Contagem de casos de teste É possível contar o número de casos de teste que estão incluídos num nó da árvore, utilizando a função testcasecount: testcasecount :: Test -> Int Contagem na árvore de testes: Só são contados os testes que são efectivamente casos de teste Acrescentando um caso de teste na raiz da árvore: tpoten = TestCase (assertequal "Simplificacao:" "8" (simplif "2^3")) suitetp = TestLabel "Polinómios" (TestList [tsomas, tprod, tpoten]) 18

Caminhos na hierarquia de testes Forma de identificar univocamente um teste da árvore de testes Tipos de dados para os representar: data Node = ListItem Int Label String deriving (Eq, Show, Read) type Path = [Node] Utiliza-se a função testcasepath para obter todos os caminhos de um teste testcasepaths :: Test -> [Path] O resultado é uma lista com todos os caminhos (que tambem são listas) desde o caso de teste em direcção ao teste indicado Exemplo na aplicação de teste: testcasepaths suitetp [[Label "Números", ListItem 0, Label "Somas", ListItem 0, Label "Polinómios"], [Label "Monomios", ListItem 1, Label "Somas", ListItem 0, Label "Polinómios"], [Label "Polinomio", ListItem 2, Label "Somas", ListItem 0, Label "Polinómios"], [Label "Números", ListItem 0, Label "Produtos", ListItem 1, Label "Polinómios"], [Label "Monomios", ListItem 1, Label "Produtos", ListItem 1, Label "Polinómios"], [Label "Polinomio", ListItem 2, Label "Produtos", ListItem 1, Label "Polinómios"], [ListItem 2, Label "Polinómios"]] 19 Caminhos na hierarquia de testes Árvore de testes com nós (testes) numerados Caminhos identificados: 20

Execução de testes Envolve a execução de um caso de teste, Se for uma árvore executa-se todos os casos de teste nela incluídos, em série (ordem decrescente de profundidade da esquerda para a direita) São mantidos quatro contadores durante a execução, definidos numa estrutura de dados: data Counts = Counts {cases, tried, errors, failures :: Int} deriving (Eq, Show, Read) Casos de teste bem sucedidos não são contabilizados, mas são de cálculo simples: tried - (errors + failures)) A atenção foca-se nos casos em que há erros ou falhas 21 Execução de testes Os testes são executados por um controlador de testes (função), com modelo de execução fixo mas pode variar a forma de apresentar resultados. Eventos aos quais o controlador de teste responde: Início de um teste Ocorrência de um erro Ocorrência de uma falha O HUnit só incluí um controlador de testes que é baseado em texto, na função: runtesttext :: PutText st -> Test -> IO (Counts, st) Pode ser adaptado fazendo variar o esquema de apresentação (reporting scheme) 22

Execução de testes O Hunit fornece uma forma mais cómoda de executar testes com um esquema de apresentação por defeito, o terminal: runtesttt :: Test -> IO Counts runtesttt t = do (counts, 0) <- runtesttext (puttexttohandle stderr True) t return counts Variantes possíveis: Enviar a saída dos testes para um ficheiro, indicando o respectivo handle Não atender a certos eventos Alterar a forma de apresentação de erros e falhas 23 Execução de testes Execução da suite de testes: runtesttt suitetp Cases: 7 Tried: 0 Errors: 0 Failures: 0 Cases: 7 Tried: 1 Errors: 0 Failures: 0 Cases: 7 Tried: 2 Errors: 0 Failures: 0 ### Failure in: Polinómios:0:Somas:2:Polinomio Simplificacao: expected: "10x^2+8x+3" but got: "12x^2+4x+5" Cases: 7 Tried: 3 Errors: 0 Failures: 1 Cases: 7 Tried: 4 Errors: 0 Failures: 1 ### Failure in: Polinómios:1:Produtos:1:Monomios Simplificacao: expected: "15x^3" but got: "14x^2" Cases: 7 Tried: 5 Errors: 0 Failures: 2 Cases: 7 Tried: 6 Errors: 0 Failures: 2 Cases: 7 Tried: 7 Errors: 0 Failures: 2 24

Funcionalidades avançadas Operadores específicos para tornar a escrita de asserções e testes mais concisa e conveniente (só quando não há mensagens): 25 Funcionalidades avançadas Utilização da função assert com sobrecarga de tipos de classes, para criação de asserções: class Assertable t where assert :: t -> Assertion instance Assertable () where assert = return instance Assertable Bool where assert = assertbool "" instance (ListAssertable t) => Assertable [t] where assert = listassert instance (Assertable t) => Assertable (IO t) where assert = (>>= assert) 26

Funcionalidades avançadas Utilização da função test com sobrecarga de tipos de classes, para criação de testes: class Testable t where test :: t -> Test instance Testable Test where test = id instance (Assertable t) => Testable (IO t) where test = TestCase. assert instance (Testable t) => Testable [t] where test = TestList. map test 27 Arquitectura do ambiente de testes O ambiente de testes tem uma arquitectura em duas camadas com quatro componentes: «executável» Aplicação a testar «biblioteca» Suite de de testes «framework» HUnit 1.0 «executável» Executor de de testes 28