SolveConPython

Python Reto #8 — FizzBuzz (versión limpia y testeable)

Nivel: Principiante
Tema: Condicionales, bucles, claridad de código, funciones puras, tests con pytest
Objetivo: Implementar FizzBuzz de forma clara, predecible y fácil de testear, evitando “scripts mágicos” y favoreciendo funciones pequeñas.

Reto #8 FizzBuzz (versión limpia y testeable)
Reto #8 FizzBuzz (versión limpia y testeable)

Enunciado

Crea una función llamada fizzbuzz(n) que:

  1. Reciba un valor n.
  2. Si n es None, lance TypeError.
  3. Si n no es un entero (int), lance TypeError.
  4. Devuelva:
    • "FizzBuzz" si n es divisible por 3 y 5,
    • "Fizz" si es divisible solo por 3,
    • "Buzz" si es divisible solo por 5,
    • el propio número n en cualquier otro caso.

No imprimas resultados. La función debe devolver un valor.

Ejemplos

  • fizzbuzz(3)"Fizz"
  • fizzbuzz(5)"Buzz"
  • fizzbuzz(15)"FizzBuzz"
  • fizzbuzz(7)7
  • fizzbuzz(0)"FizzBuzz"
  • fizzbuzz(None)TypeError
  • fizzbuzz("3")TypeError

Pistas

  1. El orden de las condiciones importa: comprueba primero el caso “3 y 5”.
  2. Usa el operador módulo % para verificar divisibilidad.
  3. Mantén la función pequeña y sin efectos secundarios.

Solución explicada (paso a paso)

  1. Validamos que n no sea None y sea un entero.
  2. Comprobamos primero si es divisible por 3 y 5.
  3. Luego comprobamos divisibilidad por 3.
  4. Luego por 5.
  5. Si no cumple ninguna condición, devolvemos el número original.

Python
def fizzbuzz(n: int) -> int | str:
"""
Devuelve Fizz, Buzz, FizzBuzz o el número según reglas clásicas.
Reglas:
- n debe ser int
- 3 y 5 -> "FizzBuzz"
- 3 -> "Fizz"
- 5 -> "Buzz"
- otro -> n
"""
if n is None or not isinstance(n, int):
raise TypeError("El parámetro 'n' debe ser un entero (int).")
if n % 15 == 0:
return "FizzBuzz"
if n % 3 == 0:
return "Fizz"
if n % 5 == 0:
return "Buzz"
return n

Python
import pytest
from reto_08_fizzbuzz import fizzbuzz
def test_fizz():
assert fizzbuzz(3) == "Fizz"
def test_buzz():
assert fizzbuzz(5) == "Buzz"
def test_fizzbuzz():
assert fizzbuzz(15) == "FizzBuzz"
def test_numero_normal():
assert fizzbuzz(7) == 7
def test_cero_es_fizzbuzz():
assert fizzbuzz(0) == "FizzBuzz"
def test_none_lanza_typeerror():
with pytest.raises(TypeError):
fizzbuzz(None)
def test_tipo_incorrecto_lanza_typeerror():
with pytest.raises(TypeError):
fizzbuzz("3")
  • pytest -q

Variantes para subir de nivel (opcional)

  1. FizzBuzz en rango: devolver lista de resultados de 1 a n
  2. Parámetros configurables: cambiar divisores y palabras
  3. Implementación funcional: separar validación y lógica
  4. Versión CLI: imprimir resultados en consola

Lo que aprendiste

  • Importancia del orden en condicionales
  • Cómo escribir funciones puras y testeables
  • Validación estricta de entradas
  • Cómo convertir un ejercicio clásico en código limpio

Accede al código completo y a los tests en GitHub para ejecutar y modificar la solución localmente.

Sigue con Reto #9 — Contar vocales en una cadena para reforzar strings, bucles y condiciones simples.