JUnit - początki z testowaniem

0

Cześć,

zabrałem się za czytanie książki o testowaniu w Javie. Książka to Practical Unit Testing. Nie rozumiem jednak kilku rzeczy związanych z testowaniem. Zacznę może jednak od kodu, który napisałem:

 
public class PasswordValidator {
	private String password;
	private static final int PASSWORD_MIN_LENGTH = 6;
	private static final ImmutableList<String> specialCharacters = ImmutableList.of("#", "@", "&");

	public boolean isPasswordLongEnough() {
		return password.length() >= PASSWORD_MIN_LENGTH;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public boolean passwordContainsSpecialCharacter() {
		for (String specialCharacter : specialCharacters) {
			if(password.contains(specialCharacter))
				return true;
		}
		return false;
	}

	public boolean passwordContainsNumber() {
		return password.matches(".*\\d+.*");
	}
}
 
@RunWith(JUnitParamsRunner.class)
public class PasswordValidatorTest {

	private PasswordValidator passwordValidator;

	private Object[] getCorrectPassword() {
		return $("passwordLon#Enough21");
	}

	private Object[] getWrongPassword() {
		return $("pass");
	}

	@Before
	public void setUp() {
		passwordValidator = new PasswordValidator();
	}

	@Test
	@Parameters(method = "getCorrectPassword")
	public void constructorShouldSetPassword(String password) {
		passwordValidator.setPassword(password);
		assertEquals(password, passwordValidator.getPassword());
	}

	@Test
	@Parameters(method = "getCorrectPassword")
	public void passwordShouldBeAtLeastSixCharactersLong(String password) {
		passwordValidator.setPassword(password);
		assertTrue(passwordValidator.isPasswordLongEnough());
	}

	@Test
	@Parameters(method = "getWrongPassword")
	public void passwordShouldBeTooShort(String password) {
		passwordValidator.setPassword(password);
		assertFalse(passwordValidator.isPasswordLongEnough());
	}

	@Test
	@Parameters(method = "getCorrectPassword")
	public void passwordShouldContainSpecialCharacter(String password) {
		passwordValidator.setPassword(password);
		assertTrue(passwordValidator.passwordContainsSpecialCharacter());
	}

	@Test
	@Parameters(method = "getCorrectPassword")
	public void passwordShouldContainsNumber(String password) {
		passwordValidator.setPassword(password);
		assertTrue(passwordValidator.passwordContainsNumber());
	}
}

Testuje walidator hasła, jako założenia przyjąłem, że musi mieć minimum 6 znaków, 1 znak specjalny, przynajmniej jedną liczbę. Testuję też setter, czy poprawnie ustawia wartość.
Mam wątpliwości, czy napisane przeze mnie testy mają sens.
Czy powinienem w każdym przypadku testować przypadek pozytywny i negatywny? Czyli sprawdzać, czy hasło zawiera znak specjalny i czy go nie zawiera?
W jaki sposób usunąć powtarzający się w każdym teście setter?
Czy coś w moim podejściu do testów wymaga zmiany?

Może to banalny temat, ale czuję się lekko oszołomiony :D

0

Testowanie settera i gettera, o ile nie zawierają żadnej logiki, jest raczej zbędne.
Jeśli chcesz 100% pokrycia to musisz testować wszystkie mozliwe przejścia przez kod (popatrz np. na jakiegoś CodeCovera, Coberture czy Emme).
Poza tym to sprawdzanie czy hasło zawiera znaki specjalne jest napisane nieoptymalnie :P Robisz tam O(n*k) operacji gdzie n to długośc hasła a k to liczba znaków specjalnych. Da się to stuknąć w czasie średnim O(n) albo jak chcesz mieć pewność pesymistycznej złożoności to O(n*logk). Zapakuj te znaki specjalne w Set (HashSet dla O(n) albo TreeSet dla O(n*logk)) i iteruj po literkach z hasła sprawdzając czy ich nie ma w tym secie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1