Duvida Com Junit

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.

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.

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.

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 :slight_smile:

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:

[code]public interface UserDAO {

public User getUserByUsernameAndPassword(String username, String password);

}[/code]
2- Essa é a nossa classe de Login

[code]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;
}

}[/code]
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

[code]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;
}

}[/code]

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”

[code]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);

}

}[/code]
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 :slight_smile: 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

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.

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

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

[code]objeto.add(1);
objeto.add(3);
objeto.add(2);

objeto.size(); // deveria ser 3[/code]

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.

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!