Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

App Engine Unit Testing: ImportError: Start directory is not importable

I'm trying to learn unit testing with Google App Engine by using the exact code they put on the Local Unit Testing for Python page (https://cloud.google.com/appengine/docs/python/tools/localunittesting). I can't figure out this error, though:

ImportError: Start directory is not importable: 'testmem.py' 

I'm just using their simple testing framework as testrunner.py and their Datastore and Memcache tests in a file called testmem.py. I call the test from the project root directory as:

<me>$ python testrunner.py ~/google_appengine testmem.py

this matches the usage as far as I can tell: %prog SDK_PATH TEST_PATH.

My file structure is:

__init__.py
app.yaml
testrunner.py
testmem.py
helloworld.py

Can anyone tell me what I'm doing wrong here? Thanks in advance.

Complete error message:

Traceback (most recent call last):
  File "testrunner.py", line 30, in <module>
    main(SDK_PATH, TEST_PATH)
  File "testrunner.py", line 17, in main
    suite = unittest.loader.TestLoader().discover(test_path)
  File "/usr/lib/python2.7/unittest/loader.py", line 204, in discover
    raise ImportError('Start directory is not importable: %r' % start_dir)
ImportError: Start directory is not importable: 'testmem.py'

testrunner.py:

#!/usr/bin/python
import optparse
import sys
import unittest

USAGE = """%prog SDK_PATH TEST_PATH
Run unit tests for App Engine apps.

SDK_PATH    Path to the SDK installation
TEST_PATH   Path to package containing test modules"""


def main(sdk_path, test_path):
    sys.path.insert(0, sdk_path)
    import dev_appserver
    dev_appserver.fix_sys_path()
    suite = unittest.loader.TestLoader().discover(test_path)
    unittest.TextTestRunner(verbosity=2).run(suite)


if __name__ == '__main__':
    parser = optparse.OptionParser(USAGE)
    options, args = parser.parse_args()
    if len(args) != 2:
        print 'Error: Exactly 2 arguments required.'
        parser.print_help()
        sys.exit(1)
    SDK_PATH = args[0]
    TEST_PATH = args[1]
    main(SDK_PATH, TEST_PATH)

testmem.py:

import unittest
from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.ext import testbed

class TestModel(db.Model):
    """A model class used for testing."""
    number = db.IntegerProperty(default=42)
    text = db.StringProperty()

class TestEntityGroupRoot(db.Model):
    """Entity group root"""
    pass

def GetEntityViaMemcache(entity_key):
    """Get entity from memcache if available, from datastore if not."""
    entity = memcache.get(entity_key)  # @UndefinedVariable
    if entity is not None:
        return entity
    entity = TestModel.get(entity_key)
    if entity is not None:
        memcache.set(entity_key, entity)  # @UndefinedVariable
    return entity

class DemoTestCase(unittest.TestCase):

    def setUp(self):    
        # First, create an instance of the Testbed class.
        self.testbed = testbed.Testbed()
        # Then activate the testbed, which prepares the service stubs for use.
        self.testbed.activate()
        # Next, declare which service stubs you want to use.
        self.testbed.init_datastore_v3_stub()
        self.testbed.init_memcache_stub()

    def tearDown(self):
        self.testbed.deactivate()

    def testInsertEntity(self):
        TestModel().put()
        self.assertEqual(1, len(TestModel.all().fetch(2)))

    def testFilterByNumber(self):
        root = TestEntityGroupRoot(key_name="root")
        TestModel(parent=root.key()).put()
        TestModel(number=17, parent=root.key()).put()
        query = TestModel.all().ancestor(root.key()).filter('number =', 42)
        results = query.fetch(2)
        self.assertEqual(1, len(results))
        self.assertEqual(42, results[0].number)

    def testGetEntityViaMemcache(self):
        entity_key = str(TestModel(number=18).put())
        retrieved_entity = GetEntityViaMemcache(entity_key)
        self.assertNotEqual(None, retrieved_entity)
        self.assertEqual(18, retrieved_entity.number)


if __name__ == '__main__':
    unittest.main()
like image 901
Mike Avatar asked Nov 14 '14 03:11

Mike


Video Answer


1 Answers

Here, "test path" should be a directory that contains the tests you want to run, not the path to a single module. Try just using . as the directory (assuming you're running it from the top-level project/app directory) and see if that helps.

My team keeps our tests in a separate directory from our source code, so we would use a path to our test directory as that second argument.

like image 66
Owen S. Avatar answered Oct 24 '22 20:10

Owen S.