Why am I getting an Assertion Error in Python? - python

I am testing a function in Python. This is the function I wrote.
def hypotenuse(a, b):
math.sqrt(a**2 + b**2)
I used this test case.
def test_hypotenuse_1(self):
self.assertEqual(funcs.hypotenuse, 3, 4)
This assertion error came up.
======================================================================
FAIL: test_hypotenuse_1 (__main__.TestCases)
----------------------------------------------------------------------
Traceback (most recent call last):
File "funcs_tests.py", line 27, in test_hypotenuse_1
self.assertEqual(funcs.hypotenuse, 3, 4)
AssertionError: <function hypotenuse at 0x7f397f2d79d8> != 3 : 4
What did I do wrong? Sorry if this is a basic question I am a first-time coder.

You need to call the function, and then specify what the result of that call is supposed to be equal to
def test_hypotenuse_1(self):
self.assertEqual(funcs.hypotenuse(3, 4), 5)
This asserts that the hypotenuse of a triangle with sides 3 and 4 is equal to 5.
Your test will still fail because hypotenuse() doesn't return the result. It needs to be:
def hypotenuse(a, b):
return math.sqrt(a**2 + b**2)
Note that you should generally not use equality testing for a mathematical function like this. It uses floating point arithmetic, which can have roundoff error. You can use the assertAlmostEqual() function for this.

Related

Local variable in Unittest subtest is not defined

I have a test task for unittest. I get the NameError error: name 'x' is not defined in each subtest.
After looking at the course material and documentation, I can't figure out what the error is. How do I fix this?
import unittest
def factorize(x):
"""
Factorize positive integer and return its factors.
:type x: int,>=0
:rtype: tuple[N],N>0
"""
pass
class TestFactorize(unittest.TestCase):
def test_wrong_types_raise_exception(self):
cases = ['string', 1]
for case in cases:
with self.subTest(x=case):
print(x)
self.assertRaises(TypeError, factorize, x)
def test_negative(self):
cases = [-1, -10, -100]
for case in cases:
with self.subTest(x=case):
self.assertRaises(ValueError, factorize, x)
def test_zero_and_one_cases(self):
cases = [0, 1]
for case in cases:
with self.subTest(x=case):
self.assertEqual(factorize(x), (x,))
def test_simple_numbers(self):
cases = [3, 13, 29]
for case in cases:
with self.subTest(x=case):
self.assertEqual(factorize(x), (x,))
if __name__ == '__main__':
unittest.main()
subtest doesn't define a new local variable x. x is just a name used as part of the error message when the test fails. You need, for example, to continue to use case in your test code itself.
def test_wrong_types_raise_exception(self):
cases = ['string', 1]
for case in cases:
with self.subTest(x=case):
print(case)
self.assertRaises(TypeError, factorize, case)
Now when the test fails, you'll see each subtest labeled with string like x=..., with the value of case that produced the failure.
======================================================================
FAIL: test_wrong_types_raise_exception (__main__.TestFactorize) (x='string')
----------------------------------------------------------------------
Traceback (most recent call last):
File "tmp.py", line 19, in test_wrong_types_raise_exception
self.assertRaises(TypeError, factorize, case)
AssertionError: TypeError not raised by factorize
Changing the call to subTest(foo=case) would cause the tag to become foo='string'.

Evaluate combinations in python

I'm python user and I'm evaluate combination in python.
For two integers m,n, nCm=n!/(m!*(n-m)!)
So, I defined factorial and combination function.
factorial function is working, but combination function does not working.
What is the error?
1> Factorial Function
def factorial(a):
f=1
for i in range(1,a+1):
f=f*i
print(f)
2> Combination Function
def Combination(n,m):
fn=factorial(n)
fm=factorial(m)
fnm=factorial(n-m)
ncm=factorial(n)/(factorial(m)*factorial(n-m))
print(ncm)
In factorial function, For example, factorial(4)=24 is working in python.
But, In combination function,
When I typing Combination(4,2),
24
2
2
24
2
2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-18-daae2b10838c> in <module>()
----> 1 Combination(4,2)
<ipython-input-17-76c6e425ad35> in Combination(n, m)
3 fm=factorial(m)
4 fnm=factorial(n-m)
----> 5 ncm=factorial(n)/(factorial(m)*factorial(n-m))
6 print(ncm)
7
TypeError: unsupported operand type(s) for *: 'NoneType' and 'NoneType'
What's the matter in my coding?
Instead of printing the output of a function, you should return the result.
def factorial(a):
f=1
for i in range(1,a+1):
f=f*i
return f
def combination(n,m):
return = factorial(n)/(factorial(m)*factorial(n-m))
print combination(4,2)
One more remark: after calculating factorial(n), it will be stored in your fn variable. You shouldn't calculate it again, but rather take that value and "recycle" it.
def factorial(a):
f=1
for i in range(1,a+1):
f=f*i
return f
def Combination(n,m):
fn=factorial(n)
fm=factorial(m)
fnm=factorial(n-m)
ncm=fn/(fm*fnm)
print(ncm)
Combination(4,2)
In your code there is missing return statement in factorial function.

Does the order of functions in a Python script matter?

Let's say I have two functions in my script: sum_numbers and print_sum. Their implementation is like this:
def sum_numbers(a, b):
return a + b
def print_sum(a, b):
print(sum_numbers(a, b))
So my question is: does the order in which the function are written matter? If I had written the print_sum function first and then the sum_numbers, would the code still work? If the answer is yes, does it always work?
The only thing that Python cares about is that the name is defined when it is actually looked up. That's all.
In your case, this is just fine, order doesn't really matter since you are just defining two functions. That is, you are just introducing two new names, no look-ups.
Now, if you called one of these (in effect, performed a look-up) and switched the order around:
def print_sum(a, b):
print(sum_numbers(a, b))
print_sum(2, 4)
def sum_numbers(a, b):
return a + b
you'd be in trouble (NameError) because it will try to find a name (sum_numbers) that just doesn't exist yet.
So in general, yes, the order does matter; there's no hoisting of names in Python like there is in other languages (e.g JavaScript).
It doesn't matter in which order the functions are created. It only matters when the call to the function is done:
def print_sum(a, b):
print(sum_numbers(a, b))
def sum_numbers(a, b):
return a + b
print_sum(1, 3)
# 4
that works because at the time print_sum is called both functions do exist. However if you call the function before defining sum_numbers it would fail because sum_numbers isn't defined yet:
def print_sum(a, b):
print(sum_numbers(a, b))
print_sum(1, 3)
def sum_numbers(a, b):
return a + b
throws:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-34-37c0e3733861> in <module>()
2 print(sum_numbers(a, b))
3
----> 4 print_sum(1, 3)
5
6 def sum_numbers(a, b):
<ipython-input-34-37c0e3733861> in print_sum(a, b)
1 def print_sum(a, b):
----> 2 print(sum_numbers(a, b))
3
4 print_sum(1, 3)
5
NameError: name 'sum_numbers' is not defined
It doesn't matter in which order functions are defined as shown below:
def display():
print(text())
def text():
return "Hello World"
display() # "Hello World" is displayed
But, it matters where functions are called so if calling "display()" at the beginning as shown below:
display() # Error
def display():
print(text())
def text():
return "Hello World"
Then, there is the error as shown below:
Traceback (most recent call last): File "", line 1, in
NameError: name 'display' is not defined

What is the real world use or significance of sphinx doctest?

What is is the significance of doctest in Sphinx? Can someone help me understand its use with a simple example.
Sphinx's doctest is for testing the documentation itself. In other words, it allows for the automatic verification of the documentation's sample code. While it might also verify whether the Python code works as expected, Sphinx is unnecessary for that purpose alone (you could more easily use the standard library's doctest module).
So, a real-world scenario (one I find myself in on a regular basis) goes something like this: a new feature is nearing completion, so I write some documentation to introduce the new feature. The new docs contain one or more code samples. Before publishing the documentation, I run make doctest in my Sphinx documentation directory to verify that the code samples I've written for the audience will actually work.
I haven't used it myself but it is my understanding that it extends the functionality of doctest. For example it adds testsetup and testcleanup directives which you can put your set-up and tear-down logic in. Making it possible for Sphinx to exclude that in the documentation.
Here is a simple example (from the doctest module):
"""
This is the "example" module.
The example module supplies one function, factorial(). For example,
>>> factorial(5)
120
"""
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
If the result is small enough to fit in an int, return an int.
Else return a long.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> [factorial(long(n)) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000L
>>> factorial(30L)
265252859812191058636308480000000L
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000L
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
"""
import math
if not n >= 0:
raise ValueError("n must be >= 0")
if math.floor(n) != n:
raise ValueError("n must be exact integer")
if n+1 == n: # catch a value like 1e300
raise OverflowError("n too large")
result = 1
factor = 2
while factor <= n:
result *= factor
factor += 1
return result
if __name__ == "__main__":
import doctest
doctest.testmod()

How to fix this python program?

import math
def p(n):
return 393000*((288200/393000)^n * math.exp(-(288200/393000)))/math.factorial(n)
print p(3)
When I run it, I get the following error message:
Traceback (most recent call last):
File "poisson.py", line 6, in <module>
print p(3)
File "poisson.py", line 4, in p
return 393000*((288200/393000)^n * math.exp(-(288200/393000)))/math.factoria
l(n)
TypeError: unsupported operand type(s) for ^: 'int' and 'float'
Replace ^ with ** in
(288200/393000)^n
Bear in mind that
288200/393000
Returns 0
Maybe you should try using decimal numbers:
import math
def p(n):
a = 393000.0 # <-- notice the .0
b = 288200.0
c = b / a
return a * ( c**n * math.exp(-c) )/ math.factorial(n)
print p(3)
Returns:
12406.890756
Is the ^ supposed to mean exponentiation? If so, use ** instead.
You can also use math.pow:
>>> import math
>>> math.pow(3,2)
9.0
Though actually it looks like maybe this isn't the best idea, since math.pow is more for C extension compatibility, and doesn't handle all the cases that ** does:
>>> 2**3000
1230231922161117176931558813276752514640713895736833715766118029160058800614672948775360067838593459582429649254051804908512884180898236823585082482065348331234959350355845017413023320111360666922624728239756880416434478315693675013413090757208690376793296658810662941824493488451726505303712916005346747908623702673480919353936813105736620402352744776903840477883651100322409301983488363802930540482487909763484098253940728685132044408863734754271212592471778643949486688511721051561970432780747454823776808464180697103083861812184348565522740195796682622205511845512080552010310050255801589349645928001133745474220715013683413907542779063759833876101354235184245096670042160720629411581502371248008430447184842098610320580417992206662247328722122088513643683907670360209162653670641130936997002170500675501374723998766005827579300723253474890612250135171889174899079911291512399773872178519018229989376L
vs.
>>> import math
>>> math.pow(2, 3000)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: math range error
see http://mail.python.org/pipermail/python-list/2003-November/236169.html for a little more detail
EDIT: In response to your question as to why it returns 0.0, that's because you are raising 0 to a power - you are using / for division, which by default is integer division and will truncate. use from __future__ import division to get floating point divison.

Categories