Que tipo de teste é esse, unidade ou funcional?

Pessoal, tenho uma dúvida com o teste abaixo.
Sei que o JUnit serve tanto para fazer testes de unidade como testes funcionais, entao minha duvida é onde se enquadra esse teste.
Existe o teste de unidade utilizando a técncia estrutural ou fucional … acredito que esse teste seja de unidade utilizando a técnica funcional…
O que vcs acham???

Essa classe foi desenvolvida em Java e o teste feito com o JUnit. Esse codigo é d um programa d imagens onde tem a classe “Add” que seve p fazer a adição entre duas imagens. Nesse caso, o teste força q tenha uma imagem aberta e ele chama o metodo pra fazer a adição dessa imagem. Após é feita a comparação do valor de alguns dos pixels da imagem resultante pra ver se está correta ( é verificado o valor do pixel em tal posição através do metodo getPixelBand).

“classe Add”

public class MethodAdd { public void execute() throws MethodException { super.execute(); ParameterBlock pb = new ParameterBlock(); pb.addSource(sources.get(0)); pb.addSource(sources.get(1)); results.addElement(JAI.create("add", pb)); }

“classe de teste Add”

[code]public class TestMethodAdd extends TestCase {
protected PlanarImage ima1, ima2, imaResulttAdd;
protected TestMethodAdd testAdd;
protected TestMethodAdd testMethodAdd;
protected ParameterBlock parameterBlock;

public void setUp() {    	
	testMethodAdd = new TestMethodAdd();
            ima1 = JAI.create("fileload", "C:\\Test.PNG");
            ima2 = JAI.create("fileload", "C:\\Test.PNG");    	
	parameterBlock = new ParameterBlock();
	parameterBlock.addSource( ima1 );
	parameterBlock.addSource( ima2 );
	
}

public void testAdd(){
imaResultAdd = JAI.create( “add”, parameterBlock );
float[] knownResult = new float[3];
knownResult[0] = 0.0f;
knownResult[1] = 128.0f;
knownResult[2] = 255.0f;

assertTrue("3.0", knownResult[0] == getPixelBand( imaResultAdd, 20, 20 )[0]);
assertTrue("4.0", knownResult[0] == getPixelBand( imaResultAdd, 20, 20 )[1]);
assertTrue("5.0", knownResult[0] == getPixelBand( imaResultAdd, 20, 20 )[2]);

}

public final float[] getPixelBand( PlanarImage src, int x, int y)
{ …
}[/code]

O foco do JUnit é teste funitário, utilizar para teste funcional não é uma boa idéia.

Este testeé unitário, testa uma classe isoladamente.

[quote]O foco do JUnit é teste funitário, utilizar para teste funcional não é uma boa idéia.

Este testeé unitário, testa uma classe isoladamente. [/quote]

Cara,

postei essa mesma duvida em outro forum, a resposta foi diferente …
se quiser conferir: http://www.javafree.org/javabb/viewtopic.jbb?t=861276

Valeu.

A linha abaixo indica que o método depende de outros recursos:

Este pode ser um teste de integração ou funcional, mas se seguirmos ao pé da letra este não é um teste de unidade.

Mas pra que você precisa classificar o tipo de teste que está sendo feito afinal?

Bom,

quase todos os testes q fiz foi assim, pois o programa q estou testando é de imagens, entao sempre vou precisar fazer a chamada a uma ou mais imagens para após verificar se a imagem resultante esta correta atraves dos valores dos pixels dela ( como no exemplo q mostrei )

Isso faz parte de um trabalho e por isso preciso classificar qual tipo de teste e q técnica eu utilizei.
Primeiramente eu achava q estava fazendo teste de unidade por estar fazendo o teste atraves do codigo, ams depois m bateu a duvida.

Mas ainda tenho duvidas!!
valeu

Foi mal, as linhas que eu devia ter citado acima eram essas:

ParameterBlock pb = new ParameterBlock(); pb.addSource(sources.get(0)); pb.addSource(sources.get(1)); results.addElement(JAI.create("add", pb));

O problema de classificar o teste que você fez como de unidade é que você não está testando somente a porção mínima de código, no caso o seu método execute().

Como este método depende das classes ParameterBlock e JAI, você acaba testando estas outras classes indiretamente.

A idéia de se usar mocks neste caso seria pra aumentar este isolamento. Embora o teste fique menos abrangente, você testa apenas o que o método realmente faz (invocar métodos de outras classes, por exemplo). Daí sim este seria um teste de unidade.

Deste modo você também não seria obrigado também a testar a imagem resultante, já que este método não a constrói (ele delega funções para outros objetos).

Sacou a diferença? São só abordagens diferentes, que podem e devem ser usadas em conjunto.

Se você seguir este princípio um teste unitário deveria utilizar mocks de qualquer classe, até mesmo strings. Teste unitário não significa que apenas o código do componente específico (classe, método, pacote, componente, serviço) deva ser testado mas sim que ele deve ser testado isoladamente de outros componentes com os quais interaja.

Se a classe precisa de um gif ou outro arquivo que é gerado por um outro processo qualquer o fato do teste suprir esta dependência, seja na forma de um arquivo físico em disco, um byte array ou outra coisa qualquer é um mock. O que importa é que o componente é testado em isolamento

[quote=pcalcado]Se você seguir este princípio um teste unitário deveria utilizar mocks de qualquer classe, até mesmo strings. Teste unitário não significa que apenas o código do componente específico (classe, método, pacote, componente, serviço) deva ser testado mas sim que ele deve ser testado isoladamente de outros componentes com os quais interaja.
[/quote]

Ok, ele está testando a unidade de trabalho isoladamente (método “execute()”), porém eu ainda acredito que o ideal seria isolar esta unidade do resto do sistema (classe ParameterBlock, por exemplo) para evitar que este se torne também um teste funcional ou de integração.
Ao meu ver o teste de unidade tem que avaliar o que o método deve fazer, ao invés de se focar resultados que dependem de outras classes.

[quote=pcalcado]
Se a classe precisa de um gif ou outro arquivo que é gerado por um outro processo qualquer o fato do teste suprir esta dependência, seja na forma de um arquivo físico em disco, um byte array ou outra coisa qualquer é um mock. O que importa é que o componente é testado em isolamento[/quote]

Usar um arquivo fictício para testes ao meu ver não é um mock, e sim um stub. Mock seria um objeto que substituiria uma dependência direta dentro do “execute()”, permitindo simplesmente verificar se este método está interagindo com os outros objetos corretamente. Acredito que estas sejam abordagens bem diferentes.

Caro s4nchez!

Voce m disse que deveria fazer um teste de unidade do “ParameterBlock” ne … Tenho a classe ParameterBlock aqui mas nao sei como eu testaria d forma isolada.

Será que poderia lhe enviar um email pra trocar uma ideia contigo a respeito disso?

Valeu!!!
Abraco

[quote=patr07souza]
Caro s4nchez!

Voce m disse que deveria fazer um teste de unidade do “ParameterBlock” ne … Tenho a classe ParameterBlock aqui mas nao sei como eu testaria d forma isolada.

Será que poderia lhe enviar um email pra trocar uma ideia contigo a respeito disso?

Valeu!!!
Abraco[/quote]

Você deve testar essa classe se foi você que a criou. Caso contrário você pode assumir que ela funciona como deveria.

Se você quiser pode me mandar e-mail, mas se puder continuar a discussão aqui (ou em um novo tópico, talvez) eu prefiro, já que mais pessoas podem aproveitar alguma coisa da nossa troca de idéias :slight_smile:

Ok!
Vou colocar aqui a classe. Deixei a documentação caso hajam duvidas … ficou um pouco extenso! :slight_smile:

/*
 * @(#)ParameterBlock.java	
  */

package java.awt.image.renderable;
import java.awt.image.RenderedImage;
import java.io.Serializable;
import java.util.Vector;

/**
 * A <code>ParameterBlock</code> encapsulates all the information about sources and
 * parameters (Objects) required by a RenderableImageOp, or other
 * classes that process images.
 *
 * <p> Although it is possible to place arbitrary objects in the
 * source Vector, users of this class may impose semantic constraints
 * such as requiring all sources to be RenderedImages or
 * RenderableImage.  <code>ParameterBlock</code> itself is merely a container and
 * performs no checking on source or parameter types.
 *
 * <p> All parameters in a <code>ParameterBlock</code> are objects; convenience
 * add and set methods are available that take arguments of base type and
 * construct the appropriate subclass of Number (such as
 * Integer or Float).  Corresponding get methods perform a
 * downward cast and have return values of base type; an exception
 * will be thrown if the stored values do not have the correct type.
 * There is no way to distinguish between the results of 
 * "short s; add(s)" and "add(new Short(s))".
 *
 * <p> Note that the get and set methods operate on references.
 * Therefore, one must be careful not to share references between
 * <code>ParameterBlock</code>s when this is inappropriate.  For example, to create
 * a new <code>ParameterBlock</code> that is equal to an old one except for an
 * added source, one might be tempted to write:
 *
 * <pre>
 * ParameterBlock addSource(ParameterBlock pb, RenderableImage im) {
 *     ParameterBlock pb1 = new ParameterBlock(pb.getSources());
 *     pb1.addSource(im);
 *     return pb1;
 * }
 * </pre>
 *
 * <p> This code will have the side effect of altering the original
 * <code>ParameterBlock</code>, since the getSources operation returned a reference
 * to its source Vector.  Both pb and pb1 share their source Vector,
 * and a change in either is visible to both.
 *
 * <p> A correct way to write the addSource function is to clone
 * the source Vector:
 *
 * <pre>
 * ParameterBlock addSource (ParameterBlock pb, RenderableImage im) {
 *     ParameterBlock pb1 = new ParameterBlock(pb.getSources().clone());
 *     pb1.addSource(im);
 *     return pb1;
 * }
 * </pre>
 *
 * <p> The clone method of <code>ParameterBlock</code> has been defined to
 * perform a clone of both the source and parameter Vectors for
 * this reason.  A standard, shallow clone is available as
 * shallowClone.
 *
 * <p> The addSource, setSource, add, and set methods are
 * defined to return 'this' after adding their argument.  This allows
 * use of syntax like:
 *
 * <pre>
 * ParameterBlock pb = new ParameterBlock();
 * op = new RenderableImageOp("operation", pb.add(arg1).add(arg2));
 * </pre>
 * */

public class ParameterBlock implements Cloneable, Serializable {
    /** A Vector of sources, stored as arbitrary Objects. */
    protected Vector<Object> sources = new Vector<Object>();
    
    /** A Vector of non-source parameters, stored as arbitrary Objects. */
    protected Vector<Object> parameters = new Vector<Object>();

    /** A dummy constructor. */
    public ParameterBlock() {}

    /** 
     * Constructs a <code>ParameterBlock</code> with a given Vector 
     * of sources. 
     * @param sources a <code>Vector</code> of source images
     */
    public ParameterBlock(Vector<Object> sources) {
        setSources(sources);
    }
    
    /**
     * Constructs a <code>ParameterBlock</code> with a given Vector of sources and
     * Vector of parameters.
     * @param sources a <code>Vector</code> of source images
     * @param parameters a <code>Vector</code> of parameters to be used in the
     *        rendering operation
     */
    public ParameterBlock(Vector<Object> sources,
			  Vector<Object> parameters)
    {
        setSources(sources);
        setParameters(parameters);
    }
    
    /**
     * Creates a shallow copy of a <code>ParameterBlock</code>.  The source and
     * parameter Vectors are copied by reference -- additions or
     * changes will be visible to both versions.
     *
     * @return an Object clone of the <code>ParameterBlock</code>.
     */
    public Object shallowClone() {
        try {
            return super.clone();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Creates a copy of a <code>ParameterBlock</code>.  The source and parameter
     * Vectors are cloned, but the actual sources and parameters are
     * copied by reference.  This allows modifications to the order
     * and number of sources and parameters in the clone to be invisible
     * to the original <code>ParameterBlock</code>.  Changes to the shared sources or
     * parameters themselves will still be visible.
     *
     * @return an Object clone of the <code>ParameterBlock</code>.
     */
    public Object clone() {
        ParameterBlock theClone;

        try {
            theClone = (ParameterBlock) super.clone();
        } catch (Exception e) {
            // We can't be here since we implement Cloneable.
            return null;
        }

        if (sources != null) {
            theClone.setSources((Vector)sources.clone());
        }
        if (parameters != null) {
            theClone.setParameters((Vector)parameters.clone());
        }
        return (Object) theClone;
    }

    /**
     * Adds an image to end of the list of sources.  The image is
     * stored as an object in order to allow new node types in the
     * future.
     *
     * @param source an image object to be stored in the source list.
     * @return a new <code>ParameterBlock</code> containing the specified
     *         <code>source</code>.
     */
    public ParameterBlock addSource(Object source) {
        sources.addElement(source);
        return this;
    }
    
    /**
     * Returns a source as a general Object.  The caller must cast it into
     * an appropriate type.
     *
     * @param index the index of the source to be returned.
     * @return an <code>Object</code> that represents the source located
     *         at the specified index in the <code>sources</code>
     *         <code>Vector</code>.
     * @see #setSource(Object, int)
     */
    public Object getSource(int index) {
        return sources.elementAt(index);
    }

    /**
     * Replaces an entry in the list of source with a new source.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param source the specified source image
     * @param index the index into the <code>sources</code> 
     *              <code>Vector</code> at which to
     *              insert the specified <code>source</code>
     * @return a new <code>ParameterBlock</code> that contains the
     *         specified <code>source</code> at the specified
     *         <code>index</code>.
     * @see #getSource(int)
     */
    public ParameterBlock setSource(Object source, int index) {
        int oldSize = sources.size();
        int newSize = index + 1;
        if (oldSize < newSize) {
            sources.setSize(newSize);
        }
        sources.setElementAt(source, index);
        return this;
    }
    
    /**
     * Returns a source as a <code>RenderedImage</code>.  This method is 
     * a convenience method.
     * An exception will be thrown if the source is not a RenderedImage.
     *
     * @param index the index of the source to be returned
     * @return a <code>RenderedImage</code> that represents the source
     *         image that is at the specified index in the 
     *         <code>sources</code> <code>Vector</code>.
     */
    public RenderedImage getRenderedSource(int index) {
        return (RenderedImage) sources.elementAt(index);
    }
    
    /**
     * Returns a source as a RenderableImage.  This method is a
     * convenience method.
     * An exception will be thrown if the sources is not a RenderableImage.
     *
     * @param index the index of the source to be returned
     * @return a <code>RenderableImage</code> that represents the source
     *         image that is at the specified index in the 
     *         <code>sources</code> <code>Vector</code>.
     */
    public RenderableImage getRenderableSource(int index) {
        return (RenderableImage) sources.elementAt(index);
    }

    /** 
     * Returns the number of source images. 
     * @return the number of source images in the <code>sources</code>
     *         <code>Vector</code>.
     */
    public int getNumSources() {
        return sources.size();
    }
    
    /** 
     * Returns the entire Vector of sources. 
     * @return the <code>sources</code> <code>Vector</code>.  
     * @see #setSources(Vector)  
     */
    public Vector<Object> getSources() {
        return sources;
    }
    
    /** 
     * Sets the entire Vector of sources to a given Vector. 
     * @param sources the <code>Vector</code> of source images
     * @see #getSources
     */
    public void setSources(Vector<Object> sources) {
        this.sources = sources;
    }
    
    /** Clears the list of source images. */
    public void removeSources() {
        sources = new Vector();
    }
    
    /** 
     * Returns the number of parameters (not including source images).
     * @return the number of parameters in the <code>parameters</code>
     *         <code>Vector</code>.
     */
    public int getNumParameters() {
        return parameters.size();
    }
    
    /** 
     * Returns the entire Vector of parameters. 
     * @return the <code>parameters</code> <code>Vector</code>.
     * @see #setParameters(Vector)
     */
    public Vector<Object> getParameters() {
        return parameters;
    }
    
    /** 
     * Sets the entire Vector of parameters to a given Vector. 
     * @param parameters the specified <code>Vector</code> of
     *        parameters
     * @see #getParameters
     */
    public void setParameters(Vector<Object> parameters) {
        this.parameters = parameters;
    }
    
    /** Clears the list of parameters. */
    public void removeParameters() {
        parameters = new Vector();
    }
    
    /** 
     * Adds an object to the list of parameters. 
     * @param obj the <code>Object</code> to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(Object obj) {
        parameters.addElement(obj);
        return this;
    }

    /** 
     * Adds a Byte to the list of parameters. 
     * @param b the byte to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(byte b) {
        return add(new Byte(b));
    }
    
    /** 
     * Adds a Character to the list of parameters. 
     * @param c the char to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(char c) {
        return add(new Character(c));
    }
    
    /** 
     * Adds a Short to the list of parameters. 
     * @param s the short to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(short s) {
        return add(new Short(s));
    }
    
    /** 
     * Adds a Integer to the list of parameters. 
     * @param i the int to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(int i) {
        return add(new Integer(i));
    }
    
    /** 
     * Adds a Long to the list of parameters. 
     * @param l the long to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(long l) {
        return add(new Long(l));
    }

    /** 
     * Adds a Float to the list of parameters. 
     * @param f the float to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(float f) {
        return add(new Float(f));
    }

    /** 
     * Adds a Double to the list of parameters. 
     * @param d the double to add to the 
     *            <code>parameters</code> <code>Vector</code>
     * @return a new <code>ParameterBlock</code> containing 
     *         the specified parameter.
     */
    public ParameterBlock add(double d) {
        return add(new Double(d));
    }

    /**
     * Replaces an Object in the list of parameters.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param obj the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(Object obj, int index) {
        int oldSize = parameters.size();
        int newSize = index + 1;
        if (oldSize < newSize) {
            parameters.setSize(newSize);
        }
        parameters.setElementAt(obj, index);
        return this;
    }

    /**
     * Replaces an Object in the list of parameters with a Byte.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param b the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(byte b, int index) {
        return set(new Byte(b), index);
    }

    /**
     * Replaces an Object in the list of parameters with a Character.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param c the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(char c, int index) {
        return set(new Character(c), index);
    }

    /**
     * Replaces an Object in the list of parameters with a Short.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param s the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(short s, int index) {
        return set(new Short(s), index);
    }

    /**
     * Replaces an Object in the list of parameters with an Integer.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param i the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(int i, int index) {
        return set(new Integer(i), index);
    }

    /**
     * Replaces an Object in the list of parameters with a Long.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param l the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(long l, int index) {
        return set(new Long(l), index);
    }

    /**
     * Replaces an Object in the list of parameters with a Float.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param f the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(float f, int index) {
        return set(new Float(f), index);
    }

    /**
     * Replaces an Object in the list of parameters with a Double.
     * If the index lies beyond the current source list,
     * the list is extended with nulls as needed.
     * @param d the parameter that replaces the 
     *        parameter at the specified index in the
     *        <code>parameters</code> <code>Vector</code>
     * @param index the index of the parameter to be 
     *        replaced with the specified parameter
     * @return a new <code>ParameterBlock</code> containing
     *        the specified parameter.
     */
    public ParameterBlock set(double d, int index) {
        return set(new Double(d), index);
    }

    /**
     * Gets a parameter as an object.
     * @param index the index of the parameter to get
     * @return an <code>Object</code> representing the
     *         the parameter at the specified index
     *         into the <code>parameters</code>
     *         <code>Vector</code>.
     */
    public Object getObjectParameter(int index) {
        return parameters.elementAt(index);
    }

    /**
     * A convenience method to return a parameter as a byte.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not a <code>Byte</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index
     *         as a <code>byte</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Byte</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public byte getByteParameter(int index) {
        return ((Byte)parameters.elementAt(index)).byteValue();
    }

    /**
     * A convenience method to return a parameter as a char.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not a <code>Character</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index       
     *         as a <code>char</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Character</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public char getCharParameter(int index) {
        return ((Character)parameters.elementAt(index)).charValue();
    }
    
    /**
     * A convenience method to return a parameter as a short.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not a <code>Short</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index       
     *         as a <code>short</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Short</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public short getShortParameter(int index) {
        return ((Short)parameters.elementAt(index)).shortValue();
    }

    /**
     * A convenience method to return a parameter as an int.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not an <code>Integer</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index       
     *         as a <code>int</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Integer</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public int getIntParameter(int index) {
        return ((Integer)parameters.elementAt(index)).intValue();
    }

    /**
     * A convenience method to return a parameter as a long.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not a <code>Long</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index       
     *         as a <code>long</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Long</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public long getLongParameter(int index) {
        return ((Long)parameters.elementAt(index)).longValue();
    }

    /**
     * A convenience method to return a parameter as a float.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not a <code>Float</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index       
     *         as a <code>float</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Float</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public float getFloatParameter(int index) {
        return ((Float)parameters.elementAt(index)).floatValue();
    }

    /**
     * A convenience method to return a parameter as a double.  An
     * exception is thrown if the parameter is 
     * <code>null</code> or not a <code>Double</code>.
     *
     * @param index the index of the parameter to be returned.
     * @return the parameter at the specified index       
     *         as a <code>double</code> value.
     * @throws ClassCastException if the parameter at the
     *         specified index is not a <code>Double</code>
     * @throws NullPointerException if the parameter at the specified
     *         index is <code>null</code>
     * @throws ArrayIndexOutOfBoundsException if <code>index</code>
     *         is negative or not less than the current size of this
     *         <code>ParameterBlock</code> object
     */
    public double getDoubleParameter(int index) {
        return ((Double)parameters.elementAt(index)).doubleValue();
    }

    /**
     * Returns an array of Class objects describing the types
     * of the parameters.
     * @return an array of <code>Class</code> objects.
     */
    public Class [] getParamClasses() {
        int numParams = getNumParameters();
        Class [] classes = new Class[numParams];
        int i;

        for (i = 0; i < numParams; i++) {
            Object obj = getObjectParameter(i);
            if (obj instanceof Byte) {
              classes[i] = byte.class;
            } else if (obj instanceof Character) {
              classes[i] = char.class;
            } else if (obj instanceof Short) {
              classes[i] = short.class;
            } else if (obj instanceof Integer) {
              classes[i] = int.class;
            } else if (obj instanceof Long) {
              classes[i] = long.class;
            } else if (obj instanceof Float) {
              classes[i] = float.class;
            } else if (obj instanceof Double) {
              classes[i] = double.class;
            } else {
              classes[i] = obj.getClass();
            }
        }
        
        return classes;
    }
}