ERROR: https://www (unittest.loader._FailedTest) while Unit Testing - python

Currently trying to write a unittest for a particular function. The error is shown below:
E
======================================================================
ERROR: https://www (unittest.loader._FailedTest)
----------------------------------------------------------------------
AttributeError: module '__main__' has no attribute 'https://www'
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (errors=1)
While the funtion itself has not been called within the Test function, I am trying to initialize a class Hasher inside the test. Commenting out the initialization line leads to the program running.
class Test(unittest.TestCase):
def test_YT(self):
self.H = Hasher()
self.assertTrue(True)
The code for the class is shown below:
class Hasher:
import hashlib
def __init__(self, hash_algo='md5'):
print('we getting here')
# TODO: support for more hash algos
self.hash_algo = hash_algo
def hash_file(self, filename):
return hashlib.md5(open(filename, 'rb').read()).hexdigest()
def compare_file_txt(self, filename, hash_txt_file):
# Useful for when there is an MD5 txt in the folder
hash1 = self.hash_file(filename)
if hash1 == open(hash_txt_file).readline():
return True
return False
def YT_create_hash(self, link, output_loc='test_hash.txt'):
DL = Downloader()
file_name = DL.YT_extract(link)
hash_txt = self.hash_file(os.getcwd() + '/' + file_name)
o_file = open(output_loc, 'w')
o_file.write(hash_txt)
o_file.close()
There's nothing in the class initialization which indicates that it is using 'https://www', so not really sure where this error is coming from.
My imports are in the form of:
from Hasher import *
from Downloader import *
And my file structure right now is:

It is almost never a good idea to use from my module import *. This can cause clashes with names imported from other modules, bugs due to the wrong function or class used, and unwanted side effects.
Try to always import only needed objects. Use tools like pylint or flake8, or the built-in hints in your IDE to be notified of similar issues.
In this concrete case, the statement from downloader import * most probably caused the problem.

Related

Subclassing TestCase in Python: Overwriting Field in Parent TestCase

I'm writing integration tests for an Alexa app.
Our application uses a controller-request-response pattern. The controller receives a request with a specified intent and session variables, routes the request to functions that do some computation with the session variables, and returns a response object with the results of that computation.
We get the right behavior from UnhandledIntentTestCase as far as test_for_smoke is concerned. However, test_returning_reprompt_text
never fires, because returns_reprompt_text is never overwritten.
Can someone explain how I can overwrite it in the parent class and/or
how the correct intent name is passed to the request object in setUpClass?
intent_base_case.py
import unittest
import mycity.intents.intent_constants as intent_constants
import mycity.mycity_controller as mcc
import mycity.mycity_request_data_model as req
import mycity.test.test_constants as test_constants
###############################################################################
# TestCase parent class for all intent TestCases, which are integration tests #
# to see if any changes in codebase have broken response-request model. #
# #
# NOTE: Assumes that address has already been set. #
###############################################################################
class IntentBaseCase(unittest.TestCase):
__test__ = False
intent_to_test = None
returns_reprompt_text = False
#classmethod
def setUpClass(cls):
cls.controller = mcc.MyCityController()
cls.request = req.MyCityRequestDataModel()
key = intent_constants.CURRENT_ADDRESS_KEY
cls.request._session_attributes[key] = "46 Everdean St"
cls.request.intent_name = cls.intent_to_test
cls.response = cls.controller.on_intent(cls.request)
#classmethod
def tearDownClass(cls):
cls.controller = None
cls.request = None
def test_for_smoke(self):
self.assertNotIn("Uh oh", self.response.output_speech)
self.assertNotIn("Error", self.response.output_speech)
def test_correct_intent_card_title(self):
self.assertEqual(self.intent_to_test, self.response.card_title)
#unittest.skipIf(not returns_reprompt_text,
"{} shouldn't return a reprompt text".format(intent_to_test))
def test_returning_reprompt_text(self):
self.assertIsNotNone(self.response.reprompt_text)
#unittest.skipIf(returns_reprompt_text,
"{} should return a reprompt text".format(intent_to_test))
def test_returning_no_reprompt_text(self):
self.assertIsNone(self.response.reprompt_text)
test_unhandled_intent.py
import mycity.test.intent_base_case as base_case
########################################
# TestCase class for unhandled intents #
########################################
class UnhandledIntentTestCase(base_case.IntentBaseCase):
__test__ = True
intent_to_test = "UnhandledIntent"
returns_reprompt_text = True
output
======================================================================
FAIL: test_correct_intent_card_title (mycity.test.test_unhandled_intent.UnhandledIntentTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/wdrew/projects/alexa_311/my_city/mycity/mycity/test/intent_base_case.py", line 44, in test_correct_intent_card_title
self.assertEqual(self.intent_to_test, self.response.card_title)
AssertionError: 'UnhandledIntent' != 'Unhandled intent'
- UnhandledIntent
? ^
+ Unhandled intent
? ^^
======================================================================
FAIL: test_returning_no_reprompt_text (mycity.test.test_unhandled_intent.UnhandledIntentTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/wdrew/projects/alexa_311/my_city/mycity/mycity/test/intent_base_case.py", line 56, in test_returning_no_reprompt_text
self.assertIsNone(self.response.reprompt_text)
AssertionError: 'So, what can I help you with today?' is not None
----------------------------------------------------------------------
This is because of execution order. The SkipIf decorators are executed once during the parsing of the IntentBaseCase class. They aren't re-executed for each class or for each call to the test function.
The decorator pattern for SkipIf is designed for use with fixed global variables such as versions of dependent modules, operating system or some other external resource who's availability can be calculated or known in the global context.
Skipping tests is also something that should be done for external reasons, not for internal ones such as the needs of a sub-class. A skip is still a kind of failing test which is indicated in the report so you can see your test suite isn't exercising the whole of the functional scope of the project.
You should redesign your base class structure so functions are only available to run if the sub-class and skip using Skip for this. My recommendation would be:
class IntentBaseCase(unittest.TestCase):
...
class RepromptBaseCase(IntentBaseCase):
def test_returning_reprompt_text(self):
self.assertIsNotNone(self.response.reprompt_text)
class NoRepromptBaseCase(IntentBaseCase):
def test_returning_no_reprompt_text(self):
self.assertIsNone(self.response.reprompt_text)
You should also consider moving the response portion out of the setUp and put it into a test_ function of it's own and change these test_returning functions into a simpler assertReprompt and assertNoReprompt functions. It's a good idea to set up the tests in setUp, but not a good idea to run the actual code there.

how to get the traceback of failed test (unittest) in the tearDown() function

I want to save all the traceback of all the exceptions from every failed test I run to an external file.
Instead of using try and except in every test i would like to use the tearDown of unittest so it will be more generic.
something like:
import traceback
import unittest
class SomeTestCase(unittest.TestCase):
def setUp(self):
pass
def test_some_test(self):
self.assertTrue(False)
def tearDown(self):
with open(logger.txt, 'a') as doc:
doc.write(traceback.format_exc())
the problem is that the exception that you get in the test_some_test cant be called with traceback in the teardown (the tracebacke return None)
any suggestion?
So after I went over a big piece of the unittest code I found a solution!
The TestCase class has an _outcome attribute.
The _outcome has a list type attribute called errors.
errors[0][1] is a tuple that is exactly like the sys.exc_info() output that contains the traceback.
So now that I have this tuple that I can use in traceback.format_exception() just like traceback.format_exc() uses it and problem solved.
def tearDown(self):
try:
etype, value, tb = self._outcome.errors[0][1]
trace = ''.join(traceback.format_exception(etype=etype, value=value, tb=tb, limit=None))
date = '{date}\n'.format(date=str(datetime.datetime.now()))
name = '\n' + self._testMethodName + '-\n'
with open(self.logger, 'a') as doc:
doc.write(name + date + trace)
except:
pass

unittest is not running my tests after reorganising file structure

Here is my structure:
directory/
__init__.py (blank)
myClass.py
test/
UnitTest.py
IntegrationTest.py
__init__.py (blank)
Let's use UnitTest as the example (both of them result in 0 tests). Feel free to critique my imports, I was fiddling around with it forever to import the class correctly so I can execute the UnitTest script. Also yes, I did copy a lot of code from other stack exchange questions in my search.
Before I moved to this structure, I had everything in one directory, so I know the test file works (outside of the imports)
import sys
from pathlib import Path
if __name__ == '__main__' and __package__ is None:
file = Path(__file__).resolve()
parent, top = file.parent, file.parents[2]
sys.path.append(str(top))
try:
sys.path.remove(str(parent))
except ValueError: # Already removed
pass
import directory.test
__package__ = 'directory.test'
from myClass import myClass
import unittest
from unittest import mock
print("Running Unit Tests...")
mc = myClass(params)
def mockingResponse(*args, **kwargs):
class MockResponse:
def __init__(self, json_data, status_code):
self.json_data = json_data
self.status_code = status_code
def json(self):
return self.json_data
#if/elses that return value
#mock.patch('myClass.requests.get', side_effect = mockingResponse)
class unitTest(unittest.TestCase):
print("this should run before test call")
def testsomefunc():
response = mc.somefunc()
differenceSet = set(response) ^ set(mockrespose from if/elses)
assert len(differenceSet) == 0
def testotherfunc():
#7 tests in total, same layout, different mockresponse
print("is this actually running")
unittest.main()
Then I get this in terminal:
privacy:~/git/directory$ python3 -m test.UnitTest.py
Running Unit Tests...
this should run before test call
is this actually running
----------------------------------------------------------------------
Ran 0 tests in 0.000s
OK
Checking online, I know it's not the issue of not having my names start with test and it's not because I have it indented wrong. Can't find much else in my search.
My only other thought is that it might be because I ran it as a module, but if I don't I have more problems with importing myClass. Of the many solutions I've tried for importing, this is the only one that has worked thus far.

Best practices for importing rarely used package in Python

My Python package depends on an external library for a few of it's functions. This is a non-Python package and can be difficult to install, so I'd like users to still be able to use my package but have it fail when using any functions that depend on this non-Python package.
What is the standard practice for this? I could only import the non-Python package inside the methods that use it, but I really hate doing this
My current setup:
myInterface.py
myPackage/
--classA.py
--classB.py
The interfaces script myInterface.py imports classA and classB and classB imports the non-Python package. If the import fails I print a warning. If myMethod is called and the package isn't installed there will be some error downstream but I do not catch it anywhere, nor do I warn the user.
classB is imported every time the interface script is called so I can't have anything fail there, which is why I included the pass. Like I said above, I could import inside the method and have it fail there, but I really like keeping all of my imports in one place.
From classB.py
try:
import someWeirdPackage
except ImportError:
print("Cannot import someWeirdPackage")
pass
class ClassB():
...
def myMethod():
swp = someWeirdPackage()
...
If you are only importing one external library, I would go for something along these lines:
try:
import weirdModule
available = True
except ImportError:
available = False
def func_requiring_weirdmodule():
if not available:
raise ImportError('weirdModule not available')
...
The conditional and error checking is only needed if you want to give more descriptive errors. If not you can omit it and let python throw the corresponding error when trying to calling a non-imported module, as you do in your current setup.
If multiple functions do use weirdModule, you can wrap the checking into a function:
def require_weird_module():
if not available:
raise ImportError('weirdModule not available')
def f1():
require_weird_module()
...
def f2():
require_weird_module()
...
On the other hand, if you have multiple libraries to be imported by different functions, you can load them dynamically. Although it doesn't look pretty, python caches them and there is nothing wrong with it. I would use importlib
import importlib
def func_requiring_weirdmodule():
weirdModule = importlib.import_module('weirdModule')
Again, if multiple of your functions import complicated external modules you can wrap them into:
def import_external(name):
return importlib.import_module(name)
def f1():
weird1 = import_external('weirdModule1')
def f2():
weird2 = import_external('weirdModule2')
And last, you could create a handler to prevent importing the same module twice, something along the lines of:
class Importer(object):
__loaded__ = {}
#staticmethod
def import_external(name):
if name in Importer.__loaded__:
return Importer.__loaded__[name]
mod = importlib.import_module(name)
Importer.__loaded__[name] = mod
return mod
def f1():
weird = Importer.import_external('weird1')
def f2():
weird = Importer.import_external('weird1')
Although I'm pretty sure that importlib does caching behing the scenes and you don't really need for manual caching.
In short, although it does look ugly, there is nothing wrong with importing modules dynamically in python. In fact, a lot of libraries rely on this. On the other hand, if it is just for an special case of 3 methods accessing 1 external function, do use your approach or my first one in case you cant to add custom sception handling.
I'm not really sure that there's any best practice in this situation, but I would redefine the function if it's not supported:
def warn_import():
print("Cannot import someWeirdPackage")
try:
import someWeirdPackage
external_func = someWeirdPackage
except ImportError:
external_func = warn_import
class ClassB():
def myMethod(self):
swp = external_func()
b = ClassB()
b.myMethod()
You can create two separate classes for the two cases. The first will be used when the the package exist . The second will used when the package does not exist.
class ClassB1():
def myMethod(self):
print("someWeirdPackage exist")
# do something
class ClassB2(ClassB1):
def myMethod(self):
print("someWeirdPackage does not exist")
# do something or raise Exception
try:
import someWeirdPackage
class ClassB(ClassB1):
pass
except ImportError:
class ClassB(ClassB2):
pass
You can also use given below approach to overcome the problem that you're facing.
class UnAvailableName(object):
def __init__(self, name):
self.target = name
def __getattr_(self, attr):
raise ImportError("{} is not available.".format(attr))
try:
import someWeirdPackage
except ImportError:
print("Cannot import someWeirdPackage")
someWeirdPackage = someWeirdPackage("someWeirdPackage")
class ClassB():
def myMethod():
swp = someWeirdPackage.hello()
a = ClassB()
a.myMethod()

Python Debug Fail - execution ends

I'm debugging Python with Visual Studio 2015 (Python Tools extension).
I'm very new to Python and strangely when i debug the bellow code, it runs to line 18, then line 19, then line 18 again where it exits unceremoniously. Doesn't hit my catch block, doesn't hit line 20 or 21. No error message. Anyone know what might be causing this?
The unit test is testing a common google api functionality found on Git Hub here.
My Code:
import unittest
import sys
import os
import exceptions
from _multiprocessing import flags
sys.path.insert(0, "C:\Users\Jamie.Marshall\Documents\Visual Studio 2015\Projects\GetDCMPlalyStationData\DCMPSDataQuery")
try:
from dfareporting_utils import get_arguments
except ImportError:
print(ImportError.message)
print('No Import')
try:
#Line18
class Test_dfareporting_utility_test(unittest.TestCase):
#Line19
def test_A(self):
flags = get_arguments(sys.argv, __doc__, parents=[argparser])
self.assertEqual(flags[0], "")
except Exception as ex:
print(ex.message)
print(ex.source)
if __name__ == '__main__':
unittest.main()
When a class is initialized, only the signature lines of the class, the code at the top level of the class and signature lines the methods inside are executed. The code in the methods is executed only when the methods are called. An example:
E class MyClass:
|
E my_class_attribute = 1
|
E def my_method(self, a):
N b = a + 1
N return b
E = excuted; N = not executed
Your try around the class will have no effect unless an error is raised on the class or the def line.
At the result your try around the class will have no effect unless an error is raised in one of that lines.
To catch an exception in a test put the try / except inside the method. But you should actually have a defined state in your test and the error should be expected or not present, so it might be the best to expect an error and test for it with with self.assertRaises(YourErrorType):

Categories