Nivel: Principiante
Tema: Strings, validación básica, reglas explícitas, manejo de errores, tests con pytest
Objetivo: Validar direcciones de email usando reglas simples y claras, sin expresiones regulares complejas.

Enunciado
Crea una función llamada validar_email(email) que:
- Reciba un valor
email. - Si
emailesNone, devuelvaFalse. - Si
emailno es unstr, lanceTypeError. - Considere un email válido si cumple todas estas reglas simples:
- Contiene exactamente un carácter
@ - Tiene texto antes y después del
@ - La parte después del
@contiene al menos un punto. - No contiene espacios
- Contiene exactamente un carácter
- Devuelva
Truesi es válido, oFalseen caso contrario.
Este reto no pretende cubrir todas las reglas reales del estándar de email. Es una validación práctica y pedagógica.
Ejemplos
validar_email("usuario@email.com")→Truevalidar_email("user.name@mail.co")→Truevalidar_email("usuario@com")→Falsevalidar_email("@email.com")→Falsevalidar_email("usuario@email")→Falsevalidar_email("usuario email.com")→Falsevalidar_email(None)→Falsevalidar_email(123)→ TypeError
Pistas
- Usa
email.count("@")para comprobar cuántos@hay. - Puedes dividir el email con
split("@"). - Verifica espacios con
" " in email.
Solución explicada (paso a paso)
- Si el email es
None, no es válido →False. - Si no es una cadena, lanzamos
TypeError. - Comprobamos que haya exactamente un
@. - Separamos el email en dos partes: usuario y dominio.
- Verificamos que ambas partes tengan contenido.
- Confirmamos que el dominio tenga al menos un punto.
- Verificamos que no haya espacios.
- Si todo se cumple, el email es válido.
Python
def validar_email(email: str | None) -> bool: """ Valida un email usando reglas simples. Reglas: - None -> False - No str -> TypeError - Un solo '@' - Texto antes y después del '@' - Dominio con al menos un punto - Sin espacios """ if email is None: return False if not isinstance(email, str): raise TypeError("El parámetro 'email' debe ser una cadena (str) o None.") if " " in email: return False if email.count("@") != 1: return False usuario, dominio = email.split("@") if not usuario or not dominio: return False if "." not in dominio: return False return True
Python
import pytestfrom reto_11_validar_email import validar_emaildef test_email_valido_simple(): assert validar_email("usuario@email.com") is Truedef test_email_valido_con_subdominio(): assert validar_email("user.name@mail.co") is Truedef test_sin_arroba(): assert validar_email("usuarioemail.com") is Falsedef test_multiples_arrobas(): assert validar_email("user@@mail.com") is Falsedef test_sin_usuario(): assert validar_email("@email.com") is Falsedef test_sin_punto_en_dominio(): assert validar_email("usuario@email") is Falsedef test_con_espacios(): assert validar_email("usuario email.com") is Falsedef test_none_devuelve_false(): assert validar_email(None) is Falsedef test_tipo_incorrecto_lanza_typeerror(): with pytest.raises(TypeError): validar_email(123)
Ejecuta:
pytest -q
Variantes para subir de nivel (opcional)
- Usar expresiones regulares simples (
re) - Separar validación en funciones pequeñas
- Permitir dominios locales (
localhost) - Comparar con validadores de librerías reales
Lo que aprendiste
- Cómo definir reglas claras de validación
- Por qué “validar simple” suele ser suficiente al inicio
- Manejo explícito de errores vs valores inválidos
- Cómo testear lógica booleana con múltiples casos
Accede al código completo y a los tests en GitHub para ejecutar y modificar la solución localmente.
Continúa con Reto #12 — Convertir una lista en un diccionario (índice → valor) para practicar estructuras de datos y enumeración.