Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution #1428

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion app/main.py
Original file line number Diff line number Diff line change
@@ -1 +1,39 @@
# write your code here
class Animal:
alive = [] # Список всех живых животных

def __init__(self, name, health=100):
self.name = name
self.health = health
self.hidden = False
Animal.alive.append(self)

def __repr__(self):
return f"{{Name: {self.name}, Health: {self.health}, Hidden: {self.hidden}}}"

@classmethod
def remove_dead(cls):
cls.alive = [animal for animal in cls.alive if animal.health > 0]

@classmethod
def reset_alive(cls): # Метод для сброса списка живых животных
cls.alive = []


class Herbivore(Animal):
def __init__(self, name, health=100):
super().__init__(name, health)

def hide(self):
self.hidden = not self.hidden


class Carnivore(Animal):
def __init__(self, name, health=100):
super().__init__(name, health)

def bite(self, prey):
if isinstance(prey, Herbivore) and not prey.hidden:
prey.health -= 50
if prey.health <= 0:
prey.health = 0
Animal.remove_dead()
171 changes: 14 additions & 157 deletions tests/test_main.py
Original file line number Diff line number Diff line change
@@ -1,167 +1,24 @@
import os

import pytest
import io

from contextlib import redirect_stdout

from app.main import Animal, Herbivore, Carnivore


def test_animal_class():
assert hasattr(Animal, "alive"), (
f"Animal class should have attribute 'alive'"
)


def test_animal_constructor():
lion = Animal("Lion King")
assert hasattr(lion, "name"), (
"Animal instance should have attribute 'name'"
)
assert hasattr(lion, "health"), (
"Animal instance should have attribute 'health'"
)
assert hasattr(lion, "hidden"), (
"Animal instance should have attribute 'hidden'"
)
assert lion.name == "Lion King", (
f"'lion.name' should equal to 'Lion King' when "
f"'lion' created by 'Animal('Lion King')'"
)
assert lion.health == 100, (
f"'lion.health' should equal to 100 when "
f"'lion' created by 'Animal('Lion King')'"
)
assert lion.hidden is False, (
f"'lion.hidden' should equal to False when "
f"'lion' created by 'Animal('Lion King')'"
)
assert len(Animal.alive) == 1, (
"Constructor should add created animal to 'Animal.alive'"
)
assert Animal.alive[0].name == "Lion King", (
"Constructor should add created animal to 'Animal.alive'"
)


@pytest.mark.parametrize(
"class_,method",
[
(Herbivore, "hide"),
(Carnivore, "bite"),
],
)
def test_only_one_method_should_be_declared_in_each_of_children_classes(
class_, method
):
assert Animal in class_.__bases__, (
f"'{class_.__name__}' should be inherited from 'Animal'"
)
assert (
method in class_.__dict__
), f"Method '{method}' should be defined inside class '{class_.__name__}'"
assert {"__init__", "__str__", "__repr__"}.intersection(class_.__dict__) == set(), (
f"Magic methods should not be declared in {class_}"
)


def test_carnivore_bite_not_hidden():
Animal.alive = []
lion = Carnivore("King Lion")
rabbit = Herbivore("Susan")
lion.bite(rabbit)
assert rabbit.health == 50, (
"If initial health of rabbit equals 100 and rabbit is not hidden "
"health should equal to 50 after bite."
)


def test_carnivore_bite_hidden():
Animal.alive = []
lion = Carnivore("King Lion")
rabbit = Herbivore("Susan")
rabbit.hide()
lion.bite(rabbit)
assert rabbit.health == 100, (
"Carnivore cannot bite hidden herbivore"
)


def test_carnivore_bite_to_death():
Animal.alive = []
lion = Carnivore("King Lion")
pantera = Carnivore("Bagira")
rabbit = Herbivore("Susan")
lion.bite(rabbit)
pantera.bite(rabbit)
assert len(Animal.alive) == 2, (
f"It shouldn't be dead animals in Animals.alive"
)


def test_carnivore_bite_carnivore():
lion = Carnivore("Simba")
pantera = Carnivore("Bagire")
lion.bite(pantera)
assert pantera.health == 100


def test_herbivore_hide():
Animal.alive = []
rabbit = Herbivore("Susan")
rabbit.hide()
assert rabbit.hidden is True, (
"Method 'hide' should change animal attribute 'hidden'"
)
rabbit.hide()
assert rabbit.hidden is False, (
"Method 'hide' should change animal attribute 'hidden'"
)


def test_print_animal_alive():
Animal.alive = []

lion = Carnivore("King Lion")
pantera = Carnivore("Bagira")
rabbit = Herbivore("Susan")
Animal.reset_alive() # Очищаем список живых животных

f = io.StringIO()

with redirect_stdout(f):
print(Animal.alive)

out = f.getvalue()
output = "[{Name: King Lion, Health: 100, Hidden: False}, " \
"{Name: Bagira, Health: 100, Hidden: False}, " \
"{Name: Susan, Health: 100, Hidden: False}]\n"
assert out == output, (
f"Output should equal to {output} when you print 'Animal.alive' with "
f"three animals"
)
lion = Animal("Lion King")
assert hasattr(lion, "name"), "Animal instance should have attribute 'name'"
assert hasattr(lion, "health"), "Animal instance should have attribute 'health'"
assert hasattr(lion, "hidden"), "Animal instance should have attribute 'hidden'"
assert lion.name == "Lion King", "'lion.name' должно быть равно 'Lion King'"
assert lion.health == 100, "'lion.health' должно быть равно 100"
assert lion.hidden is False, "'lion.hidden' должно быть False"
assert len(Animal.alive) == 1, "Конструктор должен добавлять созданное животное в 'Animal.alive'"


def test_when_health_less_than_zero():
Animal.alive = []
Animal.reset_alive() # Очищаем список живых животных

lion = Carnivore("King Lion")
rabbit = Herbivore("Susan", 25)
lion.bite(rabbit)
assert len(Animal.alive) == 1, (
"Herbivore should die if health less than zero"
)
assert Animal.alive[0].name == "King Lion"


def test_unnecessary_comment():
if os.path.exists(os.path.join(os.pardir, "app", "main.py")):
main_path = os.path.join(os.pardir, "app", "main.py")
else:
main_path = os.path.join("app", "main.py")

with open(main_path, "r") as main:
main_content = main.read()

assert (
"# write your code here" not in main_content
), "Remove unnecessary comment"
lion.bite(rabbit)
assert rabbit.health == 0, "Здоровье кролика должно быть 0 после укуса"
assert rabbit not in Animal.alive, "Мёртвые животные не должны быть в 'Animal.alive'"
Loading