daydreamer
daydreamer

Reputation: 92139

Python: no such test method: How can I execute a test method by calling it explicitly from another method?

Here is my LoginResourceHelper Test class

from flask.ext.testing import TestCase
    class LoginResourceHelper(TestCase):
        content_type = 'application/x-www-form-urlencoded'

        def test_create_and_login_user(self, email, password):
            user = UserHelper.add_user(email, password)
            self.assertIsNotNone(user)

            response = self.client.post('/', content_type=self.content_type,
                                        data=UserResourceHelper.get_user_json(
                                            email, password))
            self.assert200(response)
            # HTTP 200 OK means the client is authenticated and cookie
            # USER_TOKEN has been set

            return user

    def create_and_login_user(email, password='password'):
        """
        Helper method, also to abstract the way create and login works.
        Benefit? The guts can be changed in future without breaking the clients
        that use this method
        """
        return LoginResourceHelper().test_create_and_login_user(email, password)

When I call create_and_login_user('test_get_user'), I see error as following

 line 29, in create_and_login_user
    return LoginResourceHelper().test_create_and_login_user(email, password)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/unittest/case.py", line 191, in __init__
    (self.__class__, methodName))
ValueError: no such test method in <class 'core.expense.tests.harness.LoginResourceHelper.LoginResourceHelper'>: runTest

Upvotes: 2

Views: 2593

Answers (1)

Carlos
Carlos

Reputation: 2232

Python's unittest module (which Flask is using behind the scenes) organizes the code in a special way.

In order to run a specific method from a class that is derived of TestCase you need to do the following:

LoginResourceHelper('test_create_and_login_user').test_create_and_login_user(email, password)

What untitest does behind the scenes

In order to understand why you must do this, you need to understand how the default TestCase object works.

Normally, when inherited, TestCase is expecting to have a runTest method:

class ExampleTestCase(TestCase):
    def runTest(self):
       # Do assertions here

However if you needed to have multiple TestCases you would need to do this for every single one.

Since this is a tedious thing to do, they decided to the following:

class ExampleTestcase(TestCase):
    def test_foo(self):
        # Do assertions here

    def test_bar(self):
        # Do other assertions here

This is called a Test Fixture. But since we did not declare a runTest(), you now must specify what method you want the TestCase to run - which is what you want to do.

>>ExampleTestCase('test_foo').test_foo()
>>ExampleTestCase('test_bar').test_bar()

Normally, the unittest module will do all of this on the back end, along with some other things:

  • Adding TestCases to a Test Suite (which is normally done by using a TestLoader)
  • Calling the correct TestRunner (which will run all of the tests and report the results)

But since you are circumventing the normal unittest execution, you have to do the work that unitest regularly does.

For a really indepth understanding, I highly recommend that you read the docs unittest.

Upvotes: 9

Related Questions