Calling unittest.main() in PyCharm - AtrributeError: module '__main__' has no atrribute - python

I think this is more a PyCharm question than unittest question, but I'm studying testing from a book and this example is failing me as written. I'm running PyCharm 2016.3.2 and Python 3.6
import unittest
from name_function import get_formatted_name
class NamesTestCase(unittest.TestCase):
"""Tests for 'name_function.py'."""
def test_first_last_name(self):
"""Do names like 'Janis Joplin' work?"""
formatted_name = get_formatted_name('janis', 'joplin')
self.assertEqual(formatted_name, 'Janis Joplin')
# In book, it's just the unittest.main() , which does not work...
# So in PyCharm __name__ doesn't equal __main__ ... not sure why
# if __name__ == '__main__':
unittest.main()
Here is name_function.py:
def get_formatted_name(first, last):
"""Generate a neatly formatted full name."""
full_name = first + " " + last
return full_name.title()
If I run it as written, I get the following error:
EE
======================================================================
ERROR: test_name_function (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'test_name_function'
======================================================================
ERROR: true (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'true'
----------------------------------------------------------------------
Ran 2 tests in 0.000s
If I let the "if" statement run (or just delete the call to unittest.main()) then it works properly, with no main() call at all.
This is all in a test_name_function.py. So it seems like when running this one file (and importing name_function.py) that PyCharm does not consider this one file to be __main__ ? Is PyCharm doing something else behind the scenes?
I'm new to Python and PyCharm and trying to get my head around the structure and environment. Thanks very much guys.

You can use this method to figure it out.
suite = unittest.defaultTestLoader.loadTestsFromTestCase(NamesTestCase)
unittest.TextTestRunner().run(suite)

Related

Why is terminal providing me with zero results for this .py script?

I am learning unittest and am trying to work on the following two .py scripts but when i run on terminal it shows "ran 0 tests". What am i doing wrong?
sanity.py
def firstname(name):
return name.title()
and then the second
sanitycheck.py
import unittest
import sanity
class TestingCap(unittest.TestCase):
def firstone(self):
word = 'apple'
result = sanity.firstname(word)
self.assertEqual(result,'apple')
if __name__ == '__main__':
unittest.main()
Thank you!
By default, unittest assumes that tests in a unittest.TestCase are methods whose names begin with "test_"
Change your test method name to "test_firstone":
import unittest
import sanity
class TestingCap(unittest.TestCase):
def test_firstone(self):
word = 'apple'
result = sanity.firstname(word)
self.assertEqual(result,'apple')
if __name__ == '__main__':
unittest.main()
python sanitycheck.py
F
======================================================================
FAIL: test_firstone (__main__.TestingCap)
----------------------------------------------------------------------
Traceback (most recent call last):
File "sanitycheck.py", line 9, in test_firstone
self.assertEqual(result,'apple')
AssertionError: 'Apple' != 'apple'
- Apple
? ^
+ apple
? ^
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
You may change the behavior of unittest if you like. Check out the documentation: https://docs.python.org/3/library/unittest.html
You should name the file with test.
example: test_sanity, sanity_test, testsanity.
Your function names should begin with test then an underscore like:
def test_firstone(self):
...

newbiee query: mocking in python

I'm trying to learn Python and mocking infrastructure in Python at the same time (Due to requirement at my work place). I should also mention that I'm also not familiar with mocking feature in C++ or any other language.
So far, from what I've understood is that, with mocking, I can exercise the application code that makes OS. networking etc related calls, without actually invoking those operation.
Let's say I've an application, implemented as network.py
#!/usr/bin/env python
import sys
import socket
class NetworkService(object):
def sock_create(self):
try:
s = socket.socket()
s.close()
print "closed socket"
except Exception, err:
print "error creating socket"
sys.exit(1)
Things that I'd like to achieve with my unit test is:
Make sure that both normal and failure paths get tested.
In this case, to achieve, this I'm trying to come up with a sample unit test case that exercises the sock_create method, as below:
#!/usr/bin/env python
import unittest
import mock
from network import NetworkService
class NetworkServiceTest(unittest.TestCase):
#mock.patch('network.socket')
def test_01_sock_create(self, mock_sock):
reference = NetworkService()
mock_sock.return_value = False
# NetworkService::sock_create::s.close() should NOT get called
reference.sock_create()
self.assertFalse(mock_sock.close.called, "Failed to not call close")
mock_sock.socket.return_value = True
# NetworkService::sock_create::s.close() should get called
reference.sock_create()
# how to test this ???
#mock_sock.close.assert_called_with("")
if __name__ == '__main__':
unittest.main()
As you can see above, the last 'assert' statement is currently commented out; I'm not sure, how to check this? The following gives me error:
#!/usr/bin/env python
import unittest
import mock
from network import NetworkService
class NetworkServiceTest(unittest.TestCase):
#mock.patch('network.socket')
def test_01_sock_create(self, mock_sock):
reference = NetworkService()
mock_sock.return_value = False
reference.sock_create()
self.assertFalse(mock_sock.close.called, "Failed to not call close")
mock_sock.socket.return_value = True
reference.sock_create()
self.assertTrue(mock_sock.close.called, "Should have called s.close")
if __name__ == '__main__':
unittest.main()
and the error:
$ python tester.py
F
======================================================================
FAIL: test_01_sock_create (__main__.NetworkServiceTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/lib/python2.7/site-packages/mock/mock.py", line 1305, in patched
return func(*args, **keywargs)
File "tester.py", line 17, in test_01_sock_create
self.assertTrue(mock_sock.close.called, "Should have called s.close")
AssertionError: Should have called s.close
----------------------------------------------------------------------
Ran 1 test in 0.002s
FAILED (failures=1)
closed socket
error creating socket
NOTE that I'm using mocking in Python 2.7 (mock need to be installed as a separate module)
In network.py you are printing out a string. If you instead would print out the actual error you would see the reason why it's failing. What you would see in this case is that it's failing because of an AttributeError. AttributeError("'bool' object has no attribute 'close'",)
The reason this is happening is because you're giving the mock object the return value of True or False. Since a bool doesn't have any open or close method it'll throw that error.
A few other tips. You're using Exception which will catch all exceptions. Instead, only catch exceptions that you know will happen. Find out what exceptions socket might throw.
That way you would have discovered this earlier.

Issue testing user-defined exception when imported from module into __init__.py

I am attempting to write a large module split into multiple files while keeping it unified in a single logical module, as described in Ch. 10 of the Python Cookbook
However, in my unit test, I'm receiving an unexpected error when testing for an exception. When I am attempting to force an exception, I expect the exception package.MyExceptionError to be raised. However, my test is failing, because I am getting the exception package.module.MyExceptionError. On the other hand, when I call a function from a module that has been imported via __init__.py, I'm able to call it as package.my_function() as expected.
I've looked through the code for several PyPi modules that are similarly laid-out, but I'm not able to determine what I'm doing incorrectly, or am I misunderstanding how this should work?
Below is a dummy package, which includes the minimum code necessary to replicate the issue.
My file structure is:
Spam/
spam/
__init__.py
eggs.py
test/
test_eggs.py
Here are the contents of spam/eggs.py:
class EggError(Exception):
pass
def egg(b=True):
if b == True:
return 0
else:
raise EggError('Spam!')
if __name__ == '__main__':
pass
Here are the contents of spam/__init__.py:
from .egg import egg
from .egg import EggError
__all__ = ['egg', 'EggError', ]
if __name__ == '__main__':
pass
Here are the contents of test/test_spam.py:
import unittest
import spam
class Test(unittest.TestCase):
def test_egg(self):
self.assertEquals(spam.egg(), 0)
def test_EggError(self):
self.assertRaises(spam.EggError, spam.egg(False))
if __name__ == "__main__":
unittest.main()
These are the results I get when I run the test:
Finding files... done.
Importing test modules ... done.
======================================================================
ERROR: test_EggError (test.test_spam.Test)
----------------------------------------------------------------------
Traceback (most recent call last):
File "K:\Scripting\Python\err_test\test\test_spam.py", line 11, in test_EggError
self.assertRaises(spam.EggError, spam.egg(False))
File "K:\Scripting\Python\err_test\spam\eggs.py", line 12, in egg
raise EggError('Spam!')
spam.eggs.EggError: Spam!
----------------------------------------------------------------------
Ran 2 tests in 0.415s
FAILED (errors=1)
You are calling spam.egg() before assertRaises() has a chance to catch the exception. You should write that test as follows:
self.assertRaises(spam.EggError, spam.egg, False)
assertRaises() will call spam.egg() for you.
If you find this hard to read, you can use the context manager style instead:
with self.assertRaises(spam.EggError):
spam.egg(False)

Writing a pytest function for checking the output on console (stdout)

This link gives a description how to use pytest for capturing console outputs.
I tried on this following simple code, but I get error
import sys
import pytest
def f(name):
print "hello "+ name
def test_add(capsys):
f("Tom")
out,err=capsys.readouterr()
assert out=="hello Tom"
test_add(sys.stdout)
Output:
python test_pytest.py
hello Tom
Traceback (most recent call last):
File "test_pytest.py", line 12, in <module>
test_add(sys.stdout)
File "test_pytest.py", line 8, in test_add
out,err=capsys.readouterr()
AttributeError: 'file' object has no attribute 'readouterr'
what is wrong and what fix needed? thank you
EDIT:
As per the comment, I changed capfd, but I still get the same error
import sys
import pytest
def f(name):
print "hello "+ name
def test_add(capfd):
f("Tom")
out,err=capfd.readouterr()
assert out=="hello Tom"
test_add(sys.stdout)
Use the capfd fixture.
Example:
def test_foo(capfd):
foo() # Writes "Hello World!" to stdout
out, err = capfd.readouterr()
assert out == "Hello World!"
See: http://pytest.org/en/latest/fixture.html for more details
And see: py.test --fixtures for a list of builtin fixtures.
Your example has a few problems. Here is a corrected version:
def f(name):
print "hello {}".format(name)
def test_f(capfd):
f("Tom")
out, err = capfd.readouterr()
assert out == "hello Tom\n"
Note:
Do not use sys.stdout -- Use the capfd fixture as-is as provided by pytest.
Run the test with: py.test foo.py
Test Run Output:
$ py.test foo.py
====================================================================== test session starts ======================================================================
platform linux2 -- Python 2.7.5 -- pytest-2.4.2
plugins: flakes, cache, pep8, cov
collected 1 items
foo.py .
=================================================================== 1 passed in 0.01 seconds ====================================================================
Also Note:
You do not need to run your Test Function(s) in your test modules. py.test (The CLI tool and Test Runner) does this for you.
py.test does mainly three things:
Collect your tests
Run your tests
Display statistics and possibly errors
By default py.test looks for (configurable iirc) test_foo.py test modules and test_foo() test functions in your test modules.
The problem is with your explicit call of your test function at the very end of your first code snippet block:
test_add(sys.stdout)
You should not do this; it is pytest's job to call your test functions.
When it does, it will recognize the name capsys (or capfd, for that matter)
and automatically provide a suitable pytest-internal object for you as a call argument.
(The example given in the pytest documentation is quite complete as it is.)
That object will provide the required readouterr() function.
sys.stdout does not have that function, which is why your program fails.

name 'self' is not defined when doing an unittest?

Edit
So I did try again, with a new file called test2.py and it works. I packaged repoman , and test.py is in the src folder. I modified test.py after I created and installed my repoman egg. I think that's the problem. But thanks for the help. Do you guys think that's the exact reason?
import unittest
import requests
from repoman.core import ultraman, supported
from repoman.ext import writefile,locate_repo
class TestWriteFile(unittest.TestCase):
def setUp(self):
self.username = 'dummy'
self.password = 'dummy'
self.remote = 'http://192.168.1.138:6666/scm/hg/NCL'
def test_scm_permission(self):
"""
Test SCM login.
"""
r = requests.get("http://192.168.1.138:6666/scm/", auth=(self.username, self.password))
self.assertTrue(r.ok)
if __name__ == '__main__':
unittest.main()
Running python test.py I get this error:
Traceback (most recent call last):
File "test.py", line 7, in <module>
class TestWriteFile(unittest.TestCase):
File "test.py", line 19, in TestWriteFile
self.assertTrue(r.ok)
NameError: name 'self' is not defined
I don't think I need to overwrite __init__ function, do I? What's causing this? Why is self not defined? I already declared my superclass unittest.TestCase
Thanks.
I basically learned it from the official sample: Unittest - Basic Example
I'm not sure where the problem is coming from -- whether it's a copying error or the wrong test.py is being executed [update: or some mixed tabs-and-spaces issue, I can never figure out when those get flagged and when they don't] -- but the root cause is almost certainly an indentation error.
Note that the error message is
NameError: name 'self' is not defined
and not
NameError: global name 'self' is not defined
which #Rik Poggi got. This is exactly what happens if you move the self.assertTrue one level in/up:
~/coding$ cat test_good_indentation.py
import unittest
class TestWriteFile(unittest.TestCase):
def test(self):
"""
Doc goes here.
"""
self.assertTrue(1)
if __name__ == '__main__':
unittest.main()
~/coding$ python test_good_indentation.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
versus
~/coding$ cat test_bad_indentation.py
import unittest
class TestWriteFile(unittest.TestCase):
def test(self):
"""
Doc goes here.
"""
self.assertTrue(1)
if __name__ == '__main__':
unittest.main()
~/coding$ python test_bad_indentation.py
Traceback (most recent call last):
File "test_bad_indentation.py", line 3, in <module>
class TestWriteFile(unittest.TestCase):
File "test_bad_indentation.py", line 8, in TestWriteFile
self.assertTrue(1)
NameError: name 'self' is not defined
I don't think that what you showed is the actual code that get executed.
I and others belive that, for a couple of reasons:
If self.assertTrue(r.ok) fails then the line before will too. Therefore self.assertTrue(r.ok) won't execute. (as David Heffernan said)
And because your code looks fine.
I'd say that you probably made a typo of this kind:
def test_scm_permission(self):
^
|
and wrote something here that's not self
In some file that get executed instead of the one you're showing.
Take a look at this example:
# test.py
class MyClass:
def func(sel): # typo error here
self.name = 10
obj = MyClass()
obj.func()
And when I tried to run:
$ python3 test.py
Traceback (most recent call last):
File "test.py", line 8, in <module>
obj.func()
File "test.py", line 4, in func
self.name = 10
NameError: global name 'self' is not defined
Having a traceback similar to yours.
Note: Also if I'm not counting wrong self.assertTrue(r.ok) is on line 18, instead of line 19 (which is the number showed in your traceback).
This is a rewording of David Heffernan's comment.
The code you posted cannot be the cause of that traceback.
Consider these two lines from your code:
r = requests.get("http://192.168.1.138:6666/scm/", auth=(self.username, self.password))
self.assertTrue(r.ok)
The traceback says the error (NameError: name 'self' is not defined)
occurs on the second line (self.assertTrue(r.ok)). However, this cannot have been the case because the first line refers to self. If self were not defined, we would not get past the first line.
Therefore, the code you posted is not the code you ran.
This is an old question, but thought I'd add my two cents as it was not mentioned here. I agree with others that there is some type of spelling error in the original code. Look at this code carefully:
import unittest
import requests
class TestWriteFile(unittest.TestCase):
def setup(self):
self.username = 'dummy'
def test_scm_permission(self):
r = requests.get("http://192.168.1.138:6666/scm/", auth=(self.username, self.password))
self.assertTrue(r.ok)
The code appears okay at first glance (and lint tools will not complain); however, I wrote setup, instead of setUp (note the capital U). This causes self.username not to be defined in the test_scm_permission context, because python did not automatically call my mispelled function name. This is something else to check if you're running into this type of error, but are certain you've defined the class members correctly.
I had the same problem, but not with self. It was a regular variable, defined the line before the error occured.
It was apparently due to ... mixin tabs and spaces.
I replaced all tabs by 4 spaces, and the problem disappeared.
For some unspecified reason, instead of the traditional indentation error, I had this one.

Categories

Resources