Por Que Aserciones Personalizadas?

Las aserciones incorporadas son genericas. assertEquals(expected, actual) funciona para cualquier comparacion, pero el mensaje de falla carece de contexto. Las aserciones personalizadas agregan contexto de dominio: assertThat(user).isActive() produce: Expected user "alice@example.com" to be active, but status was SUSPENDED.

Construyendo Aserciones Personalizadas en Java

AssertJ Custom Assertions

public class UserAssert extends AbstractAssert<UserAssert, User> {
    public UserAssert(User actual) { super(actual, UserAssert.class); }

    public static UserAssert assertThat(User user) { return new UserAssert(user); }

    public UserAssert isActive() {
        isNotNull();
        if (!actual.isActive()) {
            failWithMessage("Expected user <%s> to be active but status was <%s>",
                actual.getEmail(), actual.getStatus());
        }
        return this;
    }

    public UserAssert hasRole(String role) {
        isNotNull();
        if (!actual.getRole().equals(role)) {
            failWithMessage("Expected user <%s> to have role <%s> but had <%s>",
                actual.getEmail(), role, actual.getRole());
        }
        return this;
    }
}

// Se lee como una especificacion
UserAssert.assertThat(user).isActive().hasRole("admin");

Aserciones Personalizadas en JavaScript

Playwright Custom Matchers

expect.extend({
    async toBeLoggedIn(page) {
        const isLoggedIn = await page.locator('.user-menu').isVisible();
        return {
            pass: isLoggedIn,
            message: () => isLoggedIn
                ? 'No se esperaba que la pagina estuviera logueada'
                : 'Se esperaba que la pagina estuviera logueada, pero no se encontro el menu de usuario'
        };
    },
});

await expect(page).toBeLoggedIn();

Soft Assertions

Las aserciones estandar detienen la ejecucion en la primera falla. Las soft assertions recolectan todas las fallas y las reportan al final.

Java (AssertJ SoftAssertions)

@Test
void shouldValidateUserProfile() {
    SoftAssertions softly = new SoftAssertions();
    softly.assertThat(user.getName()).isEqualTo("Alice");
    softly.assertThat(user.getEmail()).contains("@");
    softly.assertThat(user.getRole()).isEqualTo("admin");
    softly.assertThat(user.isActive()).isTrue();
    softly.assertAll(); // Reporta TODAS las fallas
}

Playwright Soft Assertions

test('validar elementos del dashboard', async ({ page }) => {
    await page.goto('/dashboard');
    await expect.soft(page.locator('.welcome')).toHaveText('Welcome, Admin');
    await expect.soft(page.locator('.stats')).toBeVisible();
    await expect.soft(page.locator('.recent-orders')).toHaveCount(5);
});

Cuando Usar Cada Tipo

TipoUsar CuandoEjemplo
IncorporadasComparaciones simplesassertEquals(200, statusCode)
PersonalizadasValidacion de dominio con mensajes clarosassertThat(user).isActive()
Soft assertionsValidar multiples propiedades independientesVerificar todos los campos de un perfil
Hamcrest matchersComposiciones complejas de condicioneseveryItem(hasProperty("active", is(true)))

Ejercicios

Ejercicio 1: Aserciones de Dominio

Crea aserciones personalizadas para una entidad Order, escribe tests usandolas, compara mensajes de falla.

Ejercicio 2: Suite de Soft Assertions

Escribe test que valide 8 propiedades con soft assertions, introduce 3 fallas, verifica que todas se reportan.

Ejercicio 3: Playwright Custom Matchers

Crea 3 matchers personalizados, usalos en suite de e-commerce, verifica claridad de mensajes de falla.