Tell us what’s happening:
I’m on my final test of the budget app and when I get to test_create_spend_chart the code keeps failing. I have looked over every single inch of my code and it is outputting the correct information, I even set up a test function and input the info that the “TEST CODE” is looking for in that test function and it output correctly. The only problem I can find is that when test_create_spend_chart runs, the test module code its self is not giving the instances enough data in order to have the same outcome they are hoping for. However I may be wrong and have just missed something completely. I would appreciate if someone would look over my code and let me know if something is wrong with my code or the test module. Thanks!
Your code so far
class Category:
def __init__(self, name):
self.name = name
self.ledger = list()
def deposit(self, amount, description=""):
# print(self.name, "Depositing")
action = {"amount": amount, "description": description}
# print("Depositing:", action)
self.ledger.append(action)
def withdraw(self, amount, description=""):
# print(self.name, "Attempting to withdraw")
if not self.check_funds(float(amount)):
# print("Withdraw Failed")
return False
amountWithdrawn = float(amount * -1)
action = {"amount": amountWithdrawn, "description": description}
self.ledger.append(action)
# print("Withdraw Successful")
return True
def get_balance(self):
total = 0
for actions in self.ledger:
amt = float(actions["amount"])
total += float(amt)
return float(total)
def transfer(self, amount, budgetCategory):
# Check if you got the funds
if not self.check_funds(amount):
return False
self.withdraw(amount, f"Transfer to {budgetCategory.name}")
budgetCategory.deposit(amount, f"Transfer from {self.name}")
return True
def check_funds(self, amount):
# used by both transfer and withdraw
return amount <= self.get_balance()
def __str__(self):
output = ""
sps = int(15 - (len(self.name) / 2))
topLine = ("*" * sps) + self.name + ("*" * sps)
if len(topLine) > 30:
topLine = topLine[1:]
output += topLine + "\n"
def CreateLine(description, amt):
lss = 23 - len(description)
fDesc = description[0:23]
leftSide = fDesc + (" " * lss)
strAmt = str("{:.2f}".format(amt))
rss = 7 - len(strAmt)
rightSide = (" " * rss) + strAmt
return leftSide + rightSide
for item in self.ledger:
output += CreateLine(item["description"], item["amount"]) + "\n"
lastLine = "Total: " + str(self.get_balance())
output += lastLine
return output
def create_spend_chart(categories):
# Grabs the total budget from all categories
def GrabTotalBudget(categs):
tAmt = 0
for cat in categs:
tAmt += cat.get_balance()
return float(tAmt)
# Finds what percent of that total budget is going to each category
def PercentFromTotal(total, amt):
percent = float(amt / total) * 100
percent = int(percent)
percent = str(percent)[0] + "0"
return int(percent)
totalAmt = GrabTotalBudget(categories)
vitalInfo = []
# pulls out the crucial data I need for the graph
for cat in categories:
name = cat.name
bal = cat.get_balance()
per = PercentFromTotal(totalAmt, bal)
circles = (per / 10) + 1
info = {"name": name, "circles": circles}
vitalInfo.append(info)
return FormatGraph(vitalInfo)
# This creates the graph output
def FormatGraph(infoArr):
output = '''Percentage spent by category\n'''
names = []
lineStartCircle = []
longestLength = 0
# Grabs the longest line so the function knows when to stop creating lines on the graph
# Also simplifies the data from infoArr
for i in range(len(infoArr)):
names.append(infoArr[i]['name'])
cStart = 12 - infoArr[i]['circles']
lineStartCircle.append(cStart)
if len(names[i]) > longestLength:
longestLength = len(names[i])
# This creates one line deals with the top half of the graph
# and is called repeatedly
def NextGraphLine(prcent, currLine, lineStarts):
output = ''
pls = 3 - (len(str(percent)))
output += (" " * pls) + str(prcent) + '| '
for circleStart in lineStarts:
if circleStart <= currLine:
output += "o"
else:
output += " "
output += " " * 2
return output
# This Creates the bottom line of the graph before it starts with the names
def BottomGraphLine(lineStarts):
output = (" " * 4)
inpsLen = len(lineStarts) * 3
inpsLen += 1
output += "-" * inpsLen
return output
# This Section works similar to "NextGraphLine" but it fills out each line of the
# bottom part of the graph
def NameLines(nameso, currLine):
output = " " * 5
for name in nameso:
curIndex = currLine - 13
if curIndex < len(name):
output += str(name)[curIndex]
else:
output += " "
output += " " * 2
return output
# data needed before drawing the graph
totalLines = 12 + longestLength
currentLine = 1
percent = 100
firstPart = True
# runs through all the lines and fills out the output
while currentLine <= totalLines:
if firstPart:
output += str(NextGraphLine(percent, currentLine, lineStartCircle)) + '\n'
percent -= 10
if percent < 0:
output += str(BottomGraphLine(lineStartCircle)) + '\n'
currentLine += 1
firstPart = False
else:
output += str(NameLines(names, currentLine))
if currentLine != totalLines:
output += '\n'
currentLine += 1
# finally returns the completed graph
return output
And This is the bit of the test_module that I seem to be having trouble with
def test_create_spend_chart(self):
self.food.deposit(900, "deposit")
self.entertainment.deposit(900, "deposit")
self.business.deposit(900, "deposit")
self.food.withdraw(105.55)
self.entertainment.withdraw(33.40)
self.business.withdraw(10.99)
actual = create_spend_chart([self.business, self.food, self.entertainment])
expected = "Percentage spent by category\n100| \n 90| \n 80| \n 70| o \n 60| o \n 50| o \n 40| o \n 30| o \n 20| o o \n 10| o o \n 0| o o o \n ----------\n B F E \n u o n \n s o t \n i d e \n n r \n e t \n s a \n s i \n n \n m \n e \n n \n t "
self.assertEqual(actual, expected, 'Expected different chart representation. Check that all spacing is exact.')
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36
.
Challenge: Budget App
Link to the challenge: