Duvida Com Junit

6 respostas
sidney.tavares

Boa tarde amigos,

Tenho muitas dúvidas na aplicação de testes em classes, estou engatinhando nisso, mas de tanto ler e ter comprovado como testes são importantes durante o desenvolvimento, assumi que preciso aprender se não quiser desenvolver software de segunda e se quiser estar ainda mais preparado para o mercado de trabalho, vou postar um exemplo simples que fiz mas que não consigo interpretar corretamente:

import javax.swing.JOptionPane;

import junit.framework.TestCase;

public class Banco2Test extends TestCase {

	public void testDigitarSenha() {
		String nome = JOptionPane.showInputDialog(null,
		"Olá Sr.(a), por favor, digite seu nome: ");
                                JOptionPane.showMessageDialog(null, "Nome: " + nome);
		assertTrue(nome == nome);
		int senha = Integer.parseInt(JOptionPane
		.showInputDialog("Digite Sua Senha: "));
		assertTrue(senha == 123);		
	}

}

O código acima, se eu testar com o Junit, não aponta erros, se eu interpretei direito, no caso da variavel nome, quando eu uso assertTrue(nome == nome), eu estou assumindo que quero que esta variável seja usada e retorne o nome que eu digitar correto? e no caso da senha eu estou assumindo que o teste só é válido caso a senha que eu digite seja 123? Pergunto isso porque não entendi a linha alterada abaixo:

assertTrue(nome == "Sidney");

Se eu executar o teste dessa maneira ele apresenta erro, isso me confundiu, por favor, se alguém tiver material e puder me dar umas explicações sobre testes unitários eu agradeceria muito. Abraços.

6 Respostas

E

Você está confundindo Java com 99% das outras linguagens.
Em Java, para comparar 2 strings, você usa equals, normalmente não se usa “==”.
A única vez em que você usa “==” ou “!=” para comparar strings é quando quer checar se a variável ou parâmetro string tem o valor null.

sidney.tavares

Entanglement,

Valeu pela dica, na verdade eu tenho que ficar mais atento, pois isso que você explicou eu sabia, mas por falta de atenção escrevi o código errado, valeu pelo toque, alterei a linha e o teste funcionou da maneira que eu queria, se eu entendi bem, no caso de um teste unitário, eu posso verificar como o método vai se comportar? É isso? Você tem algum material que trate desse assunto e possa passar? Eu tenho pesquisado sobre isso no Google, mas mais do que ver feito eu quero mesmo é entender, sempre vejo artigos mostrando como faz apenas, valeu pela ajuda.

Leozin

Sydney, que ótimo que você está querendo aprender testes. É uma coisa que realmente faz a diferença! Continue assim.

Mas aceita algumas críticas construtivas?

Espero que sim :)

Esse seu TestCase não está testando absolutamente nada. Não tem nenhum cenário definido e ainda por cima depende de intervenção humana, além de utilizar interface gráfica.

Um teste unitário deve possuir algumas premissas. Uma delas é a rapidez de execução e outra é a automatização. Existem também algumas boas práticas de testes, por exemplo, de ter pelo menos 1 assert por teste. Mas isso tu já deve ter lido por aí.

Vou dar um exemplo de teste de Login com senha.

1- Essa é a nossa interface de DAO de usuários:

public interface UserDAO {

  public User getUserByUsernameAndPassword(String username, String password);

}
2- Essa é a nossa classe de Login
public class Login {

    private UserDAO dao;

    public boolean checkCredentials(String username, String password) {
        return dao.getUserByUsernameAndPassword(username, password) != null;
    }

    public voit setUserDAO(UserDAO dao) {
       this.dao = dao;
    }
}
3- E esse é o nosso Stub. É um DAO "fake", usado especialmente em testes unitários. Ele vai simular uma situação bem específica, ou seja, vou simular um banco de dados que está gravado em um map
public class UserDAOStub implements UserDAO {

    private Map<String, User> users = new HashMap<String, User>();

    public UserDAOStub() {
      users.put("teste", new User("Teste");
    }

    public boolean checkCredentials(String username, String password) {
       return users.get(username) != null;
    }
}

agora vou fazer o nosso TestCase. Vou fazer dois testes: Um que vou passar o usuário Teste e ele tem que logar e outro usuário que ele NAO PODE deixar logar. Vamos chamar de "mario"

public LoginTest extends TestCase {

   public void test_login_com_sucesso() {
     UserDAO dao = new UserDAOStub(); //criando o nosso stub
     Login login = new Login();
     login.setUserDAO(dao); // setamos o login para usar o DAO fake
     String usuario = "teste";
     String senha = "qualquer";

     boolean resultado = login.checkCredentials(usuario, senha); //retorna true porque o usuario está no nosso map
     assertEquals(resultado, true);
   }

   public void test_login_com_falha() {
     UserDAO dao = new UserDAOStub(); //criando o nosso stub
     Login login = new Login();
     login.setUserDAO(dao); // setamos o login para usar o DAO fake
     String usuario = "mario";
     String senha = "outro";

     boolean resultado = login.checkCredentials(usuario, senha); // retorna false porque o ousuario mario nao está no nosso 'banco de dados', o map
     assertEquals(resultado, false);
   }

}
Dessa maneira, testamos unitariamente a classe Login. O acesso ao banco de dados não deve ser testado no teste unitário (pois aí já não é teste unitário e sim integração) e simulamos duas situacoes: de um cara que colocou um login correto e outro que colocou um login incorreto.

Perceba que coloquei o nome dos métodos com underscore ao invés de Camel Case. A minha justifica é que, ao colocar com underscore as classes de teste, facilita muito mais a explicação do que aquele teste unitário está testando de verdade. É algo que você vê em qualquer relatório de testes e sabe que "aquele teste fez isso". Boas práticas não precisam ser seguidas a risca em testes unitários :) Mas discutir isso é discutir sexo dos anjos, então nem vale a pena entrar em detalhe.

O importante é que tu entendas a diferença desse teste com o teu teste

Quando tu pegar bem o jeito, sugiro que tu vá dar uma olhada em mocks, cobertura etc

sidney.tavares

Ola Leozin,

Cara, criticas construtivas como a sua são sempre bem vindas, entendi sua explicação no exemplo e agradeço muito , a questão dos testes ainda e muito nebulosa pra mim, mas com exemplos, e principalmente orientações sobre uma direção pra seguir fica bem mais facil, pelo que entendi, eu devo realizar um teste unitário sempre pensando em um cenário com duas situações, a correta e a que pode vir a apresentar falha? Mais uma vez, obrigado.

peczenyj

Testar um método que só depende dos parâmetros recebidos para retornar algo e só importa o que o método retorna é "simples".

int resultado = X.soma(2,2); // resultado deve ser 4

Se vc altera o estado interno do objeto vc precisa fazer mais algum tipo de introspecção.

objeto.add(1);
objeto.add(3);
objeto.add(2);

objeto.size(); // deveria ser 3

entretanto se o seu objeto interage com outros vc pode investigar se esta interação é satisfatoria.

o uso de stubs e mocks parece ser natural.

henriqueluz

Leozin,

Muito bom o teu exemplo. Ficou bem claro e pra quem tá iniciando o aprendizado com testes, como eu também, fica bem fácil de entender.

Valeus!

Criado 29 de junho de 2011
Ultima resposta 14 de jul. de 2011
Respostas 6
Participantes 5