Nunes, Ingrid O. Correção Automática de Programas em Java

Propaganda
Testador Automático e Método de Avaliação de Programas em
Java
Ingrid Oliveira de Nunes1
Maria Lúcia Blanck Lisbôa2
exercícios adicionais. Visto que, em geral, elas
Abstract
To learn a programming
não são cobradas pelos professores, muitas dos
language implies that students make a lot of
alunos não costumam fazê-las.
programming exercises. Evaluating these
Isso ocorre devido ao fato de ser quase
exercises is something hard to be done: in a
impossível para o professor avaliar essas listas
Object-Oriented language, every class must
de exercícios. Uma turma da disciplina
be submitted to a lot of tests and, for each one
Algoritmos e Programação de uma universidade
of them, the results must be checked. This
geralmente tem cerca de quarenta alunos.
work presents a tool that automatizes the test
Submeter os programas de todos os alunos a
and the evaluation of programs done in the
testes de avaliação torna-se uma tarefa
Java language.
Keywords
programming language,
impraticável. Além disso, no caso de linguagens
learning, correctness, evaluation, Java.
orientadas a objetos, um exercício envolve na
Resumo
O aprendizado de uma
implementação de várias classes e cada uma
deveria ser corrigida separadamente.
linguagem de programação requer que alunos
No presente artigo, apresenta-se uma
façam muitos exercícios de programação. A
ferramenta desenvolvida em Java que tem por
avaliação desses exercícios é feita de forma
objetivo resolver este problema. A ferramenta
muito trabalhosa: no caso de uma linguagem
orientada a objetos, requer que cada classe
possibilita uma correção automática de classes
implementadas em Java, bem como apresenta
seja submetida a uma série de casos de teste e,
uma metodologia para a atribuição de notas às
para cada um deles, a correção dos resultados
classes avaliadas.
deve ser verificada. Este trabalho tem por
objetivo apresentar uma ferramenta que
automatiza o teste e a avaliação de programas
2. Testador Automático
feitos na linguagem Java.
O Testador Automático de Classes
Palavras Chave
linguagem de
consiste em uma aplicação Java que testa classes
programação, aprendizado, correção, avaliação,
implementadas
nessa
linguagem
de
Java.
programação. Ele executa testes presentes em
1. Introdução
Segundo Piaget[2], a aprendizagem
verdadeira é aquela que faz parte da experiência
de vida dos participantes no processo. Durante
aprendizado de uma linguagem de programação,
vê-se claramente a importância das atividades
práticas que o aluno deve ter.
Cada tópico que é ensinado nas aulas de
programação deveria ter uma aula prática
correspondente, na qual os alunos pudessem
testar aquilo que viram. O ideal seria que o
professor acompanhasse as atividades práticas e
avaliasse os programas dados como exercícios.
Muitas vezes, a freqüência dessas aulas
práticas não é suficiente para o bom aprendizado
do aluno. Normalmente, são das listas de
uma classe de teste fornecida e verifica a
correção de conjuntos de classes que possuem
uma determinada estrutura com base em um
conjunto-modelo.
A estrutura dessas classes necessita
seguir um determinado padrão especificado a
seguir:
a) Pacote Principal
deve existir um
pacote principal para cada problema de
programação, que contém os elementos de teste:
a classe de teste, as classes auxiliares e os
pacotes do professor e dos alunos. Dentro desse
pacote, a classe de teste deve estar presente, bem
como todas as classes que são utilizadas no
programa e não devem ser testadas. Na prática,
elas serão as classes que um professor fornece
______________________________________
1
Ingrid Oliveira de Nunes, Universidade Federal do Rio Grande do Sul (UFRGS), Instituto de Informática, Porto
Alegre, Brasil, 91501-970, [email protected]
2
Maria Lúcia Blanck Lisbôa, Universidade Federal do Rio Grande do Sul (UFRGS), Instituto de Informática, Porto
Alegre, Brasil, 91501-970, [email protected]
aos alunos e eles devem fazer uso dela e não
implementá-las.
b) Pacote do Professor este é o pacote
que deve conter todas as classes que servirão
como modelo para a aferição das classes de igual
funcionalidade dos programas dos alunos. As
classes presentes nesse pacote servirão como
fonte para a criação de interfaces, além disso, o
resultado de seus métodos será considerado
como correto. O pacote deve encontrar-se dentro
do pacote principal.
c) Pacotes dos Alunos dentro do pacote
principal, deve haver outros pacotes que serão os
pacotes dos alunos. Eles devem conter classes
com mesmo nome das classes presentes no
pacote do professor, bem como implementar
construtores e métodos de mesma assinatura que
as classes do professor. Não é necessária a
criação de uma interface e que os alunos a
implementem, visto que isto seria muito
avançado para alunos principiantes. Mas sim, o
professor deve fornecer um esqueleto da classe a
ser implementada.
Tendo-se o pacote estruturado da maneira
descrita, o testador automático de classes pode
ser utilizado para a avaliação dos programas dos
alunos, classe a classe, identificando com
bastante precisão os erros encontrados durante o
processo: problemas com construtores e
métodos.
2.1. Gerando Classes
Teste e do Professor
de
A solução encontrada para corrigir as
classes sem ser necessário alterar o código
desenvolvido pelos alunos foi interceptar a
criação e a invocação dos métodos da classe a
ser testada, verificando a existência de erros e o
retorno após a execução dos mesmos.
Para isso, foram criadas classes que
implementam a interface InvocationHandler do
pacote java.lang.reflect. Ela serve exatamente
para fazer essa interceptação. O problema é que
InvocationHandler atua sobre um objeto proxy e
intercepta os métodos das interfaces públicas da
classe do objeto, o que implica a necessidade de
todos os programas seguirem exatamente as
mesmas interfaces determinadas pelo ´esqueleto´
fornecido pelo professor.
A geração das classes de testes consiste
na criação de um pacote chamado tester
localizado dentro do pacote principal. Seu
conteúdo serão pacotes com os nomes das
classes a serem testadas. Cada um desses pacotes
terá:
Uma classe chamada com o nome da
classe a ser testada concatenado com
o nome da classe de teste. Esta será a
classe de teste.
Um pacote chamado temp que
conterá todas as classes que não a
alvo do teste, bem como a interface
extraída a partir da classe do
professor.
Um pacote chamado teacher contendo
a classe a ser testada.
Nas classes dos dois primeiros itens,
todas as instanciações da classe a ser testada
serão substituídas pela instanciação de um objeto
proxy que tem a invocação dos construtores da
classe a ser testada interceptada. Este objeto, por
sua vez, fará a instanciação de outro objeto
proxy e este será responsável por interceptar a
invocação dos métodos da classe. Além disso,
será adicionada a importação do pacote principal
em todas as classes para caso elas façam uso de
classes fornecidas pelo professor.
Obtendo-se esta estrutura de classes, é
possível iniciar o teste das classes dos alunos.
2.2.
Alunos
Testando
Classes
de
Tendo-se a estrutura de pacotes, classes e
interfaces prontas para a execução dos testes,
basta então rodá-los.
Ao iniciar a execução de um teste, o
programa faz algumas modificações no código
do aluno. Basicamente, coloca a classe a ser
testada no pacote tester.nomedaclasse.student e
acrescenta o código necessário para a classe
implementar a interface gerada a partir da classe
do professor.
Em seguida, é feita a compilação da
classe. Nesta etapa, podem aparecer erros, seja
por causa de erros de programação do aluno, seja
por causa da não implementação correta da
interface. Caso tudo ocorra corretamente, a
classe de teste iniciará sua execução. Cada
construtor e método da classe a ser testada será
interceptado ao ser chamado e será executado
tanto para a classe do professor como para a
classe do aluno. Considerando-se correta a
implementação da classe do professor, erros na
classe do aluno serão computados.
Esse processo é feito com cada uma das
classes a ser testada e, ao final, temos a relação
número de testes e número de erros de cada uma
das classes, possibilitando a atribuição de uma
nota à classe testada.
3. Método de Avaliação
A correção de uma determinada classe
pode ser vista de duas maneiras:
Correção Funcional: quando construtores e
métodos são executados corretamente e os
métodos retornam valores coerentes com o
que é esperado.
Correção de Estado: quando os campos
privativos ou não do objeto representam
corretamente o estado que ele se encontra.
Neste trabalho, optou-se por efetuar uma
correção funcional das classes, permitindo-se ao
aluno uma maior flexibilidade na implementação
de sua classe, Em [4], é feita uma verificação de
cada campo do objeto sendo testado após a
execução de cada método. Isso implica que o
aluno não tem a liberdade de optar campos
deverão fazer parte de sua classe.
Durante os testes, são verificados três
tipos de erros, relacionados a seguir.
3.1. Erro de Compilação
Ocorre quando a classe do aluno não
compila por erro de programação, ou por não
implementar a interface (esqueleto da classe
fornecido pelo professor) ou pela inexistência da
classe. A classes com erros deste tipo, são
atribuídas notas zero (0).
3.2. Ocorrência de Exceções
Ocorre após a instanciação de um objeto
ou a execução de um método. São consideradas
como erro apenas as execuções que ocorrem com
a classe do aluno e que não são declaradas na
assinatura do construtor ou do método. No caso
da ocorrência da exceção também na classe do
professor, a exceção não é contabilizada como
erro.
3.3.
Incorreto
Retorno
de
Método
Ocorre após a execução de um método
que retorne algo que não seja void. O retorno do
professor é comparado com o do aluno. Caso
eles difiram, o erro é contabilizado.
4. Interface Gráfica
O uso do Testador Automático de Classes
é realizado por meio de interfaces gráficas, que
simplificam os passos de avaliação. O primeiro
passo é abrir o pacote que se deseja testar,
selecionando-se o diretório correspondente.
Pode-se visualizar a estrutura do pacote aberto
ao lado esquerdo da janela do testador. É
possível abrir as classes a fim de ver os seu
código dando-se um duplo clique sobre a classe
a ser analisada.
Ao solicitar a execução de um teste,
deve-se selecionar a classe de teste e o pacote do
professor. A princípio, todas as classes testadas
terão peso um (1) no cálculo da nota final, mas
isso pode ser alterado clicando-se no botão Peso
das Notas...
e atribuindo-se os valores
desejados. Feito isso, basta clicar no botão
Executar Teste .
Após a execução de testes de todas as
classes de todos os alunos, um relatório será
exibido com as notas parciais e finais de todos os
alunos. Este relatório pode ser salvo como um
arquivo texto.
5. Estudo de Caso
Aqui, será apresentado um exemplo do
uso de Testador Automático de Classes.
Um professor deseja que seus alunos
implementem duas classes: a classe Pessoa e a
Classe Aluno. Para sua implementação o aluno
deve fazer o uso da classe Data, fornecida pelo
professor, e a classe que irá testar as duas classes
será a classe ClasseDeTeste. O professor deve
fornecer o esqueleto das classes a seus alunos,
como exemplificado na figura 1.
Figura 1
Cada aluno deverá implementar a sua
versão das classes solicitadas. Uma estrutura de
classes deverá ser montada, como pode ser visto
na figura 2.
Tendo os testes executados com sucesso,
cada pacote de cada aluno conterá um arquivo
texto com o relatório de teste de cada classe e
uma janela será exibida com o relatório de teste
do pacote (figura 6), o qual pode ser salvo como
um arquivo de texto.
Figura 2
Tendo isso feito, basta executar os testes.
O professor deve solicitar a execução clicando
no item Executar Teste encontrado menu
arquivo. A seguir, uma a caixa de diálogo será
exibida, como é mostrado na figura 3.
Figura 3
Aqui, o professor escolhe qual será a
classe de teste e qual será o pacote modelo (do
professor), bem como configurar os pesos das
notas das classes para o cálculo da nota final. A
figura 4 é caixa de diálogo onde se realiza esta
configuração.
Figura 4
Clicando em Executar Teste, os testes
serão iniciados. Pode-se acompanhar o
andamento da execução através de um caixa de
diálogo como a da figura 5.
Figura 5
Figura 6
6. Observações
No processo de desenvolvimento e
correção das classes, alguns aspectos devem ser
analisados:
O primeiro passo para a correção das
classes é a geração das classes de teste e
do professor. Caso elas não compilem, o
teste é abortado.
As classes do professor devem sobrepor
o método equals herdado da classe
Object do pacote java.lang. Isso permite
uma comparação do retorno dos métodos.
As classes testadas não podem conter
métodos que recebem como parâmetro ou
retornam objetos dela mesma.
Caso o método toString herdado da
classe Object do pacote java.lang seja
sobreposto, deve-se ter o cuidado para
manter um padrão do string de retorno,
pois eles serão comparados letra a letra.
Semântica igual e sintaxe diferente para
esses strings implicam num retorno
considerado incorreto do método. Mesmo
que o método toString não seja invocado
explicitamente na classe de teste, ele
pode ser chamado indiretamente, como,
por exemplo, ao chamar o método
System.out.println.
Caso ocorra algum erro de execução na
classe de teste devido a alguma classe do
professor, o teste da classe será
interrompido e será atribuída a nota
máxima à classe testada. Uma notificação
no relatório será exibida.
7.
Conclusões
Perspectivas Futuras
e
Este trabalho reflete a preocupação de
fazer com que alunos que estejam aprendendo
uma linguagem de programação tenham
atividades práticas em paralelo a o que aprendem
nas aulas teóricas. A importância da
implementação é fundamental para a fixação do
uso dos comandos de controle, dos recursos da
linguagem e o desenvolvimento do raciocínio.
O professor deve sempre acompanhar a
execução dessas atividades práticas. Para tornar
esse acompanhamento viável desenvolveu-se
uma ferramenta que automatiza tanto a correção
como a avaliação de exercícios de programação
na linguagem Java.
Esta ferramenta, faz projeto JEduc[1], o
qual já possui um ambiente de programação em
Java simplificado, ideal para quem está
aprendendo a linguagem. Além disso, possui
uma ferramenta que constrói automaticamente
classes de teste[8][9]. Futuramente, deseja-se
integrar essa ferramenta ao testador automático
de forma que a criação da classe de teste
utilizada no testador também seja gerada
automaticamente.
Deseja-se,
também,
disponibilizar o uso dessas ferramentas no
próprio IDE do JEduc.
8. Referências
[1] Brugnara, T., Bertagnolli, S. C.,
Lisboa, M. L. B., Perego, C. A. JEduc: uma
ferramenta livre para auxiliar o ensino da
linguagem de programação Java. WORKSHOP
SOFTWARE LIVRE, (WSL 2002), 2002, Porto
Alegre.
[2]
Construtivismo
em
Piaget.
http://www.comp.ufla.br/~kacilene/educacao/pia
get.html, agosto 2001.
[3] Goldwasser, M. H. A Gimmick to
Integrate Software Testing Throughout the
Curriculum. In: ACM SIGCSE Bulletin. March
2002.
[4] Hitchner, L. E. An Automatic Testing
and Grading Method for a C++ List Class. In:
ACM SIGCSE Bulletin. June 1999
[5] Jones, E. L. Integrating Testing into
the Curriculum Arsenic in Small Doses. In:
ACM SIGCSE Bulletin, Proceedings of the
thirty-second SIGCSE technical symposium on
Computer Science. February 2001
[6] Jones, E. L. Grading Student
Programs
a Software Testing. In: Grading
Student Programs
a Software Testing.
November 2000
[7] Kay, D. G. et al. Automated Grading
Assistance For Student Programs. In: ACM
SIGCSE Bulletin , Proceedings of the twentyfifth SIGCSE symposium on Computer science
education. March 1994
[8] Lima, Márcia J. Geração Automática
de Classes Testadoras em Java. Poster - Salão de
Iniciação Científica - UFRGS, Novembro de
2003
[9] Lima, Márcia J. Geração Automática
de Classes Testadoras em Java. Poster - Jornadas
de Iniciação Científica - SBPC, Cuiabá, julho de
2004
[10] Sun Microsystems. www.sun.com,
junho 2003.
Download