These kinds of things wouldn't normally be tested with a unit test, but instead they would be enforced with a class invariant in the __init__ method:
# animal.py
class Animal:
def __init__(self, name, energy=100):
if not isinstance(name, str):
raise TypeError("name should be a string")
if energy <= 0:
raise ValueError("energy has to be more than 0")
self.name = name
self.energy = energy
This way you can never even accidentally create an Animal with invalid values in it.
Of course, after setting those invariants, you can test that they are actually in place. For example with the popular pytest module:
import pytest
from animal import Animal
def test_init_ok():
animal = Animal("name", 100)
assert animal.name == "name"
assert animal.energy == 100
def test_init_bad_name():
with pytest.raises(TypeError):
animal = Animal(123, 100)
def test_init_bad_energy():
with pytest.raises(ValueError):
animal = Animal("name", 0)
with pytest.raises(ValueError):
animal = Animal("name", -100)
Or by using the built-in unittest module:
import unittest
from animal import Animal
class AnimalTests(unittest.TestCase):
def test_init_ok(self):
animal = Animal("name", 100)
self.assertEqual(animal.name, "name")
self.assertEqual(animal.energy, 100)
def test_init_bad_name(self):
with self.assertRaises(TypeError):
animal = Animal(123, 100)
def test_init_bad_energy(self):
with self.assertRaises(ValueError):
animal = Animal("name", 0)
with self.assertRaises(ValueError):
animal = Animal("name", -100)