Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

s3 bucket state isn't persisting as I expect #4967

Open
BenjaminCaffrey opened this issue Mar 24, 2022 · 7 comments
Open

s3 bucket state isn't persisting as I expect #4967

BenjaminCaffrey opened this issue Mar 24, 2022 · 7 comments
Labels

Comments

@BenjaminCaffrey
Copy link

BenjaminCaffrey commented Mar 24, 2022

I'm primarily referencing this Class Decorator piece of documentation. This leads me to believe that state created or modified in setUp(self): will persist through tests. I run that code and it looks great.

Please let me know if this is a fundamental Python or unittest misunderstanding, but here is my snippet:

import unittest
import boto3
from moto import mock_s3


@mock_s3
class TestMotoBugBaseClass:
    def setUp(self):
        client = boto3.client("s3")
        client.create_bucket(Bucket="test_bucket")

        num_buckets = len(
            [bucket.name for bucket in boto3.resource("s3").buckets.all()]
        )
        self.assertEqual(num_buckets, 1)  # Looks like we have a bucket!

    def test_bug(self):
        num_buckets = len(
            [bucket.name for bucket in boto3.resource("s3").buckets.all()]
        )
        self.assertEqual(num_buckets, 1)


class TestInheritingClass(TestMotoBugBaseClass, unittest.TestCase):
    pass

Expected: I expect that the bucket we create as part of the setUp method will persist into the test_bug method.

Actual: This test fails - we see 0 buckets returned during execution of test_bug.


Version: I have tried this in both 1.3.14 and the most recent 3.1.1 with similar results.

Thank you for any guidance! Appreciate working with moto so far, slightly confused on by this particular behavior.

@bblommers
Copy link
Collaborator

Hi @BenjaminCaffrey, welcome to Moto! It does work like this, by extending the BaseClass with the unittest.TestCase-class:

@mock_s3
class TestMotoBugBaseClass(unittest.TestCase):
    ...

Note that executing the TestMotoBugBaseClass-class also fails in this non-Moto example, because the setUp-method is not only executed for classes that extend unittest.TestCase.

class TestMotoBugBaseClass:
    def setUp(self):
        self.x = True

    def test_bug(self):
        print(self.x)


class TestInheritingClass(TestMotoBugBaseClass, unittest.TestCase):
    pass

@bblommers
Copy link
Collaborator

Having said that, looking at your example, running TestInheritingClass should pass, as this does extend the unittest.TestCase. I'll do some debugging to see why this fails.

@bblommers bblommers added the bug label Mar 24, 2022
@BenjaminCaffrey
Copy link
Author

Thank you @bblommers ! Let me know if there's anything I can do to help.

To clarify my understanding of the situation:

In your snippet, if we were to run python -m unittest on the file, we run TestInheritingClass (because it inherits from unittest.TestCase, which will call setUp and subsequently test_bug (because it also inherits from TestMotoBugBaseClass, and we see that self.x = True. So in that case test_bug is sort of "state aware" of what happened in SetUp.

But when we do the same thing with moto and mocked boto3 state (the snippet I posted), it doesn't seem to be the case.

@bblommers
Copy link
Collaborator

Yes, that is correct.

The class-decorator is responsible for resetting the state between tests. On basic classes, it will reset before every test-method. If the class extends unittest.TestCase, it will reset the state before the setUp-method instead.

The underlying issue is that the class-decorator acts on compile-time. The only context we have at that point, is that we are extending TestMotoBugBaseClass - but Moto doesn't know that we will be extending TestCase.

It may be possible to change the implementation, so that we figure this out at run-time. At run-time we do know whether we are extending TestCase. Considering that there is a workaround, and the potential to introduce other bugs, I'm going to consider this low-priority though.

@Seluj78
Copy link

Seluj78 commented Nov 25, 2023

Hi @bblommers !

Have you had any time to look into this since this issue was last updated ? :)

@bblommers
Copy link
Collaborator

Not really @Seluj78 - I haven't found a good solution to this problem yet

@Seluj78
Copy link

Seluj78 commented Nov 25, 2023

I understand. For now I guess I will have to decorate each class individually :/

Although if you do find any idea on how to solve this, I'd love to hear it! I am certain it would be a really appreciated feature for unit test users 😉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants