• 
      

    Default Action Tests for Read-Only Mode

    Review Request #8861 — Created March 31, 2017 and submitted

    Information

    khp
    Review Board
    master

    Reviewers

    Read-only mode is a setting an admin can enable to prevent writes to
    the database. This can be used when the site is under maintenence or
    being upgraded. This commit adds testing for changes to the action
    buttons visible in the tabs of a review request.

    Run pytests - all pass except some known errors

    Description From Last Updated

    Can you move this to the top of the imports, since mock is part of the Python Standard Library? And …

    szhangszhang

    Do we want to refactor this into a mixin that does common tests for actions that respect read-only mode?

    brenniebrennie

    You didn't make these changes, but shouldn't the docstrings for the tests involving anonymous users says ...with anonymous user instead …

    szhangszhang

    I noticed in the tests above that they specify that the user is authenticated. Perhaps you could mention that as …

    szhangszhang

    Closing quote on next line.

    brenniebrennie

    LIkewise.

    brenniebrennie

    I think you should be more specific with the condition for the unit test here. So, you should include a …

    szhangszhang

    I think you forgot to add periods at the end of your comments with these changes. Same with the other …

    szhangszhang

    We have test users from the test-users fixture. You can do: self.request.user = User.objects.get(username='doc') This user is not a superuser …

    brenniebrennie

    Same here (mention the permission?).

    szhangszhang

    See above comment about user fixture.

    brenniebrennie

    This probably does not really matter, but I think in the previous code you put 'perms' before 'request'. Probably should …

    JO joycezhou47

    Same here (mention the permission?).

    szhangszhang

    Same here (mention the permission?).

    szhangszhang

    Closing quote on next line.

    brenniebrennie

    We are trying to move away from Mock (as it is a rather heavy dependency), although I understand that previous …

    brenniebrennie

    Missing a period.

    brenniebrennie

    Closing quote on next line.

    brenniebrennie

    See my previous comment about the user fixture.

    brenniebrennie

    See my previous comment about the user fixture. You can use the admin user here.

    brenniebrennie

    We have an admin user: admin = User.objects.get(username='admin') review_request = self.create_review_request( create_repository=True, submitter=admin) self.request.user = admin

    brenniebrennie

    Two blank line between imports and first declaration.

    brenniebrennie

    Missing docstring.

    brenniebrennie

    Missing docstring.

    brenniebrennie

    This should indicate in its name that its a mixin of tests, e.g., ReadOnlyActionTestsMixin. Missing docstring.

    brenniebrennie

    When you do: class Foo: @add_fixtures(['..']) def test_foo(self): pass it is actually equivalent to: class Foo: def test_foo(self): pass test_foo …

    brenniebrennie

    Instead of doing this every test, how about...

    brenniebrennie

    Use ~reviewboard.reviews.actions.BaseReviewRequestAction and it will render the link with the text of only "BaseReviewRequestAction".

    brenniebrennie

    we do: try: self.siteconfig.set('site_read_only', True) self.siteconfig.save() #... rest of test finally: self.siteconfig.set('site_read_only', defaults.get('site_read_only')) self.siteconfig.save() This prevents some unnecessary siteconfig saving …

    brenniebrennie
    KH
    szhang
    1. Whoa, this is a long diff. Here some little things I noticed:

    2. Show all issues

      Can you move this to the top of the imports, since mock is part of the Python Standard Library?

      And a blank line in-between that and the django/djblets imports, of course.

      1. mock is not part of the standard library.

    3. Show all issues

      You didn't make these changes, but shouldn't the docstrings for the tests involving anonymous users says ...with anonymous user instead of ...with authenticated user?

      Same below.

    4. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
       
      Show all issues

      I noticed in the tests above that they specify that the user is authenticated. Perhaps you could mention that as well?

      Same with the test directly below.

    5. Show all issues

      I think you should be more specific with the condition for the unit test here.

      So, you should include a mention about the can_change_status permission. Something like Testing CloseMenuAction.should_render for user with can_change_status permission but in read-only mode

      Same with some tests below.

    6. Show all issues

      I think you forgot to add periods at the end of your comments with these changes.

      Same with the other comments in your changes.

    7. Show all issues

      Same here (mention the permission?).

    8. Show all issues

      Same here (mention the permission?).

    9. Show all issues

      Same here (mention the permission?).

    10. 
        
    brennie
    1. 
        
    2. Show all issues

      Do we want to refactor this into a mixin that does common tests for actions that respect read-only mode?

    3. Show all issues

      Closing quote on next line.

    4. Show all issues

      LIkewise.

    5. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
      Show all issues

      We have test users from the test-users fixture. You can do:

      self.request.user = User.objects.get(username='doc')
      

      This user is not a superuser (username admin is).

    6. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
      Show all issues

      See above comment about user fixture.

    7. Show all issues

      Closing quote on next line.

    8. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
      Show all issues

      We are trying to move away from Mock (as it is a rather heavy dependency), although I understand that previous tests in this file are using it.

      Ideally all of these would be replaced with a fake resolver match class:

      class FakeResolverMatch(object):
          def __init__(self, url_name):
              self.url_name = url_name
      

      This will ultimately result in fewer lines of code.

    9. Show all issues

      Missing a period.

    10. Show all issues

      Closing quote on next line.

    11. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
      Show all issues

      See my previous comment about the user fixture.

    12. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
      Show all issues

      See my previous comment about the user fixture.

      You can use the admin user here.

    13. reviewboard/reviews/tests/test_actions.py (Diff revision 2)
       
       
       
       
       
      Show all issues

      We have an admin user:

      admin = User.objects.get(username='admin')
      review_request = self.create_review_request(
          create_repository=True,
          submitter=admin)
      self.request.user = admin
      
    14. 
        
    JO
    1. 
        
    2. Show all issues

      This probably does not really matter, but I think in the previous code you put 'perms' before 'request'. Probably should keep this consistent?

    3. 
        
    KH
    brennie
    1. 
        
    2. reviewboard/reviews/tests/test_actions.py (Diff revision 3)
       
       
       
      Show all issues

      Two blank line between imports and first declaration.

    3. Show all issues

      Missing docstring.

    4. Show all issues

      Missing docstring.

    5. Show all issues

      This should indicate in its name that its a mixin of tests, e.g., ReadOnlyActionTestsMixin.

      Missing docstring.

    6. reviewboard/reviews/tests/test_actions.py (Diff revision 3)
       
       
       
       
       
      Show all issues

      When you do:

      class Foo:
          @add_fixtures(['..'])
          def test_foo(self): pass
      

      it is actually equivalent to:

      class Foo:
          def test_foo(self): pass
          test_foo = add_fixtures(['..'])(test_foo)
      

      so you should actually replace the functions on the instance:

      self.test_should_render_with_user_in_read_only = _add_fixtures(self.test_should_render_with_user_in_read_only)
      self.test_should_render_with_superuser_in_read_only = _add_fixtures(self.test_should_render_with_superuser_in_read_only)
      
      1. Hey Barret

        I've tried a bunch of different stuff here but not completely sure about the reasoning for why I have to do it this way, but I think it's something like this:

        The decorator function, when used as a decorator (i.e. @add_fixtures([ ... ]) is given the function, not the wrapped bound or unbound method. So I get attribute errors from the decorator trying to do func._fixtures = ... if a method is passed in, as _add_fixtures(self.test_should_render_with_user_in_read_only) would do, but no errors if used as a regular decorator. This explains why I'm using .__func__, to access the function in the wrapped method.

        I tried setting self.test_should_render_with_user_in_read_only = ..., but if this is done in __init__, it seems to replace the current bounded method with the function, and I lose the reference to self, as it now expects the self argument.

        It seems a little hacky, but I wasn't sure of a better way to both pass fixtures into the mixin from the superclass and add them to the test functions, as I can't add arguments to the decorators like usual (@add_fixtures(...)) if I want to use a mixin.

    7. reviewboard/reviews/tests/test_actions.py (Diff revision 3)
       
       
       
       
       
       
       
       
      Show all issues

      Instead of doing this every test, how about...

    8. Show all issues

      Use ~reviewboard.reviews.actions.BaseReviewRequestAction and it will render the link with the text of only "BaseReviewRequestAction".

    9. reviewboard/reviews/tests/test_actions.py (Diff revision 3)
       
       
       
       
       
       
       
       
      Show all issues

      we do:

      try:
          self.siteconfig.set('site_read_only', True)
          self.siteconfig.save()
      
          #... rest of test
      finally:
          self.siteconfig.set('site_read_only', defaults.get('site_read_only'))
          self.siteconfig.save()
      

      This prevents some unnecessary siteconfig saving when nothing has changed.

      Same for the below test.

      1. Nice catch, this is much better.

    10. 
        
    KH
    david
    Review request changed
    Status:
    Completed
    Change Summary:

    Pushed to release-4.0.x (768aab467)