Python unittesting for a class method - python

A beginner level question.. trying to understand how I can best use the built-in unittest. In the trivial example below, the method consume_food picks a food item and then I am calling food.cut() method.
In future, this method may return instance of Drink object. The #commented code indicates one possible future implementation. In this case, self.milk will not have the cut method defined.
I want to add a unit test for consume_food and pick_food methods. I would like to do this for the original implementation first and then change it after adding self.milk functionality.
EDIT: The intention is to write a unit test for an existing api, so that I can capture any such changes ( i.e. absence of Drink.cut method) forcing me to update the methods and unit tests.
Can someone please help showing me how to write a unit test for this example?
class Fruit:
def cut(self):
print("cut the fruit")
class Drink:
def pour(self):
print("pour the drink")
class A:
def __init__(self):
self.apple = Fruit()
self.banana=Fruit()
#self.milk = Drink()
#self.liquid_diet = True
def consume_food(self):
food = pick_food()
food.cut()
print("consuming the food")
def pick_food(self):
return self.apple
#if self.liquid_diet: return self.milk
#return self.apple

The thing is, your cut() and consume_food() methods don't really do much right now that allow you to make meaningful assertions after you execute them in a test.
So I'd suggest to expand your initial code a little bit to have those methods act upon the respective objects so that you can make meaningful assertions on their state after invoking those methods.
Right now, all they really do is write to STDOUT, which is sort of a global state - which should generally be avoided and is always difficult to test. (I'm not saying that printing output is a bad thing - but if that's the only thing your code does, it's going to be very tricky to test).
So I introduced a common superclass Food which has a consume() method, and sets a corresponding attribute. Similarly, the cut() method on Fruit now sets an attribute that you can test for.
import unittest
class Food(object):
def __init__(self):
self.consumed = False
def consume(self):
self.consumed = True
class Fruit(Food):
def __init__(self):
super(Fruit, self).__init__()
self.been_cut = False
def cut(self):
print("cut the fruit")
self.been_cut = True
class Consumer(object):
def __init__(self):
self.apple = Fruit()
self.banana = Fruit()
def consume_food(self):
food = self.pick_food()
food.cut()
print("consuming the food")
food.consume()
def pick_food(self):
return self.apple
These tests now can make assertions on the object's states after the relevant methods have been invoked. Note that they follow the AAA pattern - Arrange Act Assert:
First, you arrange the objects under test the way you need them (instantiate a consumer).
Then you act on the objects under test (invoking the method in question)
Finally, you make assertions on the resulting state you expect the objects to be in
class TestConsumer(unittest.TestCase):
def test_consume_food_consumes_the_apple(self):
c = Consumer()
c.consume_food()
self.assertTrue(c.apple.consumed,
"Expected apple to be consumed")
def test_consume_food_cuts_the_food(self):
c = Consumer()
c.consume_food()
self.assertTrue(c.apple.been_cut,
"Expected apple to be cut")
def test_pick_food_always_selects_the_apple(self):
c = Consumer()
food = c.pick_food()
self.assertEquals(c.apple, food,
"Expected apple to have been picked")
if __name__ == '__main__':
unittest.main()

Related

How to use inner class in python?

class Tesla_car:
def __init__(self,yourname):
self.name = yourname
print("Hey'%s',I am a bot and I will tell you about....." %self.name)
self.cells = self.batteries()
def material(self,model_no):
self.model = model_no
print("your car",self.model," made from aluminium")
def color(self,color):
self.color = color
print("the color of your car is:'%s'" %self.color)
class batteries:
def __init__(self):
pass
def materials(self):
self.battery_name = "Tesla tabless 4680 cells"
self.chemicals = "Tesla uses Lithium-Nickle-cobalt-magnesium(NMC) mixed in 8:1:1 ratio"
EV_car = Tesla_car('Blah')
EV_car()
Hey everyone, I am trying to use nested classes but whenever I try to use the inner class by writing self.cells = self.batteries() It raises an error:"Tesla_car' object has no attribute 'batteries"
How do I fix it
It seems that you're trying to compose objects, but in the wrong way.
Actually your classes reflect a perfect irl scenario for implementing composition: cars are equipped (composed) with a set of different objects, batteries included.
When using composition, you'd typically define TeslaCar and Batteries as separate classes, and then you would assign an instance of Batteries to one of TeslaCar instance variables. E.g.:
class Batteries:
def __init__(self):
...
class TeslaCar:
def __init__(self):
self.batteries = Batteries()
...
The above code is just a simple skeleton of how composition is implemented, but you can adapt it to your case very easily.
Finally FYI, avoid nesting classes at all. It's unpythonic and you'll discover that it's useless as soon as you dive deep into simple oop patterns like composition and inheritance.
Change
self.batteries()
to
Tesla_car.batteries()
your batteries inner class is wrongly indented.
Currently it is inside the color method instead of being at the same level as the method.
class TeslaCar:
def color(...):
...
class Batteries:
...
instead, do:
class TeslaCar:
def color(...):
...
class Batteries:
...

How would I 'listen' to/decorate a setter from an imported class

I'm not sure whether this is a great approach to be using, but I'm not hugely experienced with Python so please accept my apologies. I've tried to do some research on this but other related questions have been given alternative problem-specific solutions - none of which apply to my specific case.
I have a class that handles the training/querying of my specific machine learning model. This algorithm is running on a remote sensor, various values are fed into the object which returns None if the algorithm isn't trained. Once trained, it returns either True or False depending on the classification assigned to new inputs. Occasionally, the class updates a couple of threshold parameters and I need to know when this occurs.
I am using sockets to pass messages from the remote sensor to my main server. I didn't want to complicate the ML algorithm class by filling it up with message passing code and so instead I've been handling this in a Main class that imports the "algorithm" class. I want the Main class to be able to determine when the threshold parameters are updated and report this back to the server.
class MyAlgorithmClass:
def feed_value(self):
....
class Main:
def __init__(self):
self._algorithm_data = MyAlgorithmClass()
self._sensor_data_queue = Queue()
def process_data(self):
while True:
sensor_value = self._sensor_data_queue.get()
result, value = self._algorithm_data.feed_value(sensor_value)
if result is None:
# value represents % training complete
self._socket.emit('training', value)
elif result is True:
# value represents % chance that input is categoryA
self._socket.emit('categoryA', value)
elif result is False:
...
My initial idea was to add a property to MyAlgorithmClass with a setter. I could then decorate this in my Main class so that every time the setter is called, I can use the value... for example:
class MyAlgorithmClass:
#property
def param1(self):
return self._param1
#param1.setter
def param1(self, value):
self._param1 = value
class Main:
def __init__(self):
self._algorithm_data = MyAlgorithmClass()
self._sensor_data_queue = Queue()
def watch_param1(func):
def inner(*args):
self._socket.emit('param1_updated', *args)
func(*args)
My problem now, is how do I decorate the self._algorithm_data.param1 setter with watch_param1? If I simply set self._algorithm_data.param1 = watch_param1 then I will just end up setting self._algorithm_data._param1 equal to my function which isn't what I want to do.
I could use getter/setter methods instead of a property, but this isn't very pythonic and as multiple people are modifying this code, I don't want the methods to be replaced/changed for properties by somebody else later on.
What is the best approach here? This is a small example but I will have slightly more complex examples of this later on and I don't want something that will cause overcomplication of the algorithm class. Obviously, another option is the Observer pattern but I'm not sure how appropriate it is here where I only have a single variable to monitor in some cases.
I'm really struggling to get a good solution put together so any advice would be much appreciated.
Thanks in advance,
Tom
Use descriptors. They let you customize attribute lookup, storage, and deletion in Python.
A simplified toy version of your code with descriptors looks something like:
class WatchedParam:
def __init__(self, name):
self.name = name
def __get__(self, instance, insttype=None):
print(f"{self.name} : value accessed")
return getattr(instance, '_' + self.name)
def __set__(self, instance, new_val):
print(f"{self.name} : value set")
setattr(instance, '_' + self.name, new_val)
class MyAlgorithmClass:
param1 = WatchedParam("param1")
param2 = WatchedParam("param2")
def __init__(self, param1, param2, param3):
self.param1 = param1
self.param2 = param2
self.param3 = param3
class Main:
def __init__(self):
self._data = MyAlgorithmClass(10, 20, 50)
m = Main()
m._data.param1 # calls WatchedParam.__get__
m._data.param2 = 100 # calls WatchedParam.__set__
The WatchedParam class is a descriptor and can be used in MyAlgorithmClass to specify the parameters that need to be monitored.
The solution I went for is as follows, using a 'Proxy' subclass which overrides the properties. Eventually, once I have a better understanding of the watched parameters, I won't need to watch them anymore. At this point I will be able to swap out the Proxy for the base class and continue using the code as normal.
class MyAlgorithmClassProxy(MyAlgorithmClass):
#property
def watch_param1(self):
return MyAlgorithmClass.watch_param1.fget(self)
#watch_param1.setter
def watch_param1(self, value):
self._socket.emit('param1_updated', *args)
MyAlgorithmClass.watch_param1.fset(self, value)

How to implement a factory class?

I want to be able to create objects based on an enumeration class, and use a dictionary. Something like this:
class IngredientType(Enum):
SPAM = auto() # Some spam
BAKE_BEANS = auto() # Baked beans
EGG = auto() # Fried egg
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class BakedBeans(Ingredient):
pass
class Egg(Ingredient):
pass
class IngredientFactory(object):
"""Factory makes ingredients"""
choice = {
IngredientType.SPAM: IngredientFactory.MakeSpam,
IngredientType.BAKED_BEANS: IngredientFactory.MakeBakedBeans,
IngredientType.EGG: IngredientFactory.MakeEgg
}
#staticmethod
def make(type):
method = choice[type]
return method()
#staticmethod
def makeSpam():
return Spam()
#staticmethod
def makeBakedBeans():
return BakedBeans()
#staticmethod
def makeEgg():
return Egg()
But I get the error:
NameError: name 'IngredientFactory' is not defined
For some reason the dictionary can't be created.
Where am I going wrong here?
Python is not Java and doesn't require everything to be in a class. Here your IngredientFactory class has no states and only staticmethods, so it's actually just a singleton namespace, which in python is canonically done using the module as singleton namespace and plain functions. Also since Python classes are already callable, wrapping the instanciation in a function doesn't make sense. The simple, straightforwrad pythonic implementation would be:
# ingredients.py
class IngredientType(Enum):
SPAM = auto() # Some spam
BAKE_BEANS = auto() # Baked beans
EGG = auto() # Fried egg
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class Beans(Ingredient):
pass
class Egg(Ingredient):
pass
_choice = {
IngredientType.SPAM: Spam,
IngredientType.BAKED_BEANS: Beans,
IngredientType.EGG: Egg
}
def make(ingredient_type):
cls = _choice[ingredient_type]
return cls()
And the client code:
import ingredients
egg = ingredients.make(ingredients.IngredientType.EGG)
# or much more simply:
egg = ingredients.Egg()
FWIW the IngredientType enum doesn't bring much here, and even makes things more complicated that they have to be - you could just use plain strings:
# ingredients.py
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class Beans(Ingredient):
pass
class Egg(Ingredient):
pass
_choice = {
"spam": Spam,
"beans": Beans,
"egg": Egg
}
def make(ingredient_type):
cls = _choice[ingredient_type]
return cls()
And the client code:
import ingredients
egg = ingredients.make("egg")
Or if you really want to use an Enum, you can at least get rid of the choices dict by using the classes themselves as values for the enum as suggested by MadPhysicist:
# ingredients.py
class Ingredient(object):
pass
class Spam(Ingredient):
pass
class Beans(Ingredient):
pass
class Egg(Ingredient):
pass
class IngredientType(Enum):
SPAM = Spam
BEANS = Beans
EGG = Egg
#staticmethod
def make(ingredient_type):
return ingredient_type.value()
and the client code
from ingredients import IngredientType
egg = IngredientType.make(IngredientType.EGG)
But I really don't see any benefit here either
EDIT: you mention:
I am trying to implement the factory pattern, with the intent of hiding the creation of objects away. The user of the factory then just handles 'Ingredients' without knowledge of the concrete type
The user still have to specify what kind of ingredients he wants (the ingredient_type argument) so I'm not sure I understand the benefit here. What's your real use case actually ? (the problem with made up / dumbed down examples is that they don't tell the whole story).
After looking at Bruce Eckel's book I came up with this:
#Based on Bruce Eckel's book Python 3 example
# A simple static factory method.
from __future__ import generators
import random
from enum import Enum, auto
class ShapeType(Enum):
CIRCLE = auto() # Some circles
SQUARE = auto() # some squares
class Shape(object):
pass
class Circle(Shape):
def draw(self): print("Circle.draw")
def erase(self): print("Circle.erase")
class Square(Shape):
def draw(self): print("Square.draw")
def erase(self): print("Square.erase")
class ShapeFactory(object):
#staticmethod
def create(type):
#return eval(type + "()") # simple alternative
if type in ShapeFactory.choice:
return ShapeFactory.choice[type]()
assert 0, "Bad shape creation: " + type
choice = { ShapeType.CIRCLE: Circle,
ShapeType.SQUARE: Square
}
# Test factory
# Generate shape name strings:
def shapeNameGen(n):
types = list(ShapeType)
for i in range(n):
yield random.choice(types)
shapes = \
[ ShapeFactory.create(i) for i in shapeNameGen(7)]
for shape in shapes:
shape.draw()
shape.erase()
This gets the user to select a class type from the enumeration, and blocks any other type. It also means user's are less likely to write 'bad strings' with spelling mistakes. They just use the enums.
The output from the test is then, something like this:
Circle.draw
Circle.erase
Circle.draw
Circle.erase
Square.draw
Square.erase
Square.draw
Square.erase
Circle.draw
Circle.erase
Circle.draw
Circle.erase
Square.draw
Square.erase
Place your mapping at the end of the class, and reference the methods directly, since they're in the same namespace:
choice = {
IngredientType.SPAM: makeSpam,
IngredientType.BAKED_BEANS: makeBakedBeans,
IngredientType.EGG: makeEgg
}
A class object is not created until all the code in the class body, so you can't access the class itself. However, since the class body is processed in a dedicated namespace, you can access any attribute you've defined up to that point (which is why the mapping has to come at the end). Note also that while you can access globals and built-ins, you can't access the namespaces of enclosing classes or functions.
Here's the detailed but still introductory explanation from the official docs explaining how classes are executed: https://docs.python.org/3/tutorial/classes.html#a-first-look-at-classes

Modify Class Object Argument Based On When Calling A Method

This is a heavily simplified version of what I am working on, I just don't want to put 5,000 lines in here. So I know this works and all, but I want to be able to have the method"eat" be able to be applied non-specifically to any object that this class parents (such as "John Smith", and adding lets say "Mike Doe".) I would like it to automatically select the person who undergoes ".eat()" to eat food rather than making the method specifically state: johnSmith.hunger = False. What I am doing is creating methods of actions people can use within the game that affect other objects (class children and variables), but I don't want to set a method for each action for each character unit. That would be insane. Given below is my set of code.
class human():
def __init__(self, name, hunger):
self.name = name
self.hunger = hunger
def eat(self):
johnSmith.hunger = False
print("Human Ate Food")
johnSmith = human("John Smith", True)
print("Human Is Hungry:", johnSmith.hunger)
johnSmith.eat()
print("Human Is Hungry:", johnSmith.hunger)
If I am unclear (which I know I am Not doing a great job explaining), feel free to ask.
Just use self:
def eat(self):
self.hunger = False
print("%s Ate Food" % self.name)

Tick method in a PoliceOfficer class

My question deals with creating a tick procedure the original tick procedure where it makes a class called PoliceOfficer arrest everyone who is naked around him.
def tick(self):
# next time step for all objects that tick
for t in self.__things:
obj = self.get_thing(t)
if has_method(obj, "tick"):
obj.tick()
This the original tick method.
This is my PoliceOfficer class and the method known as arrest. The arrest method arrests someone based upon them not having any clothes on when in the area of the PoliceOfficer, and when there isn't anyone to arrest he just says something else.
class PoliceOfficer (Person):
def __init__(self, name, jail):
Person.__init__(self, name)
self.set_restlessness(0.5)
self.__jail = jail
def arrest (self, Person):
if self.location.name is Person.location.name:
self.say (Person.name + "You're under arrest!")
self.say ("You have the right to shut up and lay on the ground with your hands behind your back")
Person.name(Place("jail")
else:
return self.say (Person.name + "Ain't got nothing to do damnit")
def tick (self):
if isinstance(t, Student):
if Student.is_dressed = False:
arrest.student
else:
(Person)tick(): self.say("Shoot no one to arrest off to the 7 eleven")
Would this be partially correct on making my own tick method for PoliceOfficer?
If not what else would I need to do or change to make it like the tick method described, except for making the PoliceOfficer arrest any student that isn't dressed?
Uhm,... you want to test is an object is of a certain class? Python has a built-in function for that: isinstance(). Quick example:
>>> isinstance(1, int)
True
>>> isinstance("Hello World!", int)
False
>>> isinstance("Hello World!", str)
True
Check the documentation for more information.
http://docs.python.org/library/functions.html#isinstance
As per delnan's "suggestion", a little piece of advice: instead of checking for the class behind the Person you receive, it's cleaner to have Person implement a canBeArrested() method that subclasses can override, for which Student can return false.
class Person(object):
(...)
def canBeArrested(self):
return True
class Diplomat(Person):
(...)
def canBeArrested(self):
# Overrides Person's default behaviour
return False
There are two ways:
obj.__class__.__name__ == "Student"
or
isinstance(obj, Student)
I recommend the second way, but sometimes you really need the name of the class, for which obj.__class__.__name__ is the way to go.

Categories