1

I am working with locust and I am working in mimicking the behavior of a user. However I am getting trouble accessing the parent class variable. Any idea how I can pass it?

class User(TaskSet):
  some_user = ''

  def on_start(self):
    self.get_user()

  def get_user(self):
    some_user = self.client.get...#gets user

  @task
  class UpdatingUser(TaskSet):
    def updating(self):
      path = "/posts/" + User.some_user

By the time I get to User.some_user I never have the user.

Beto
  • 806
  • 3
  • 12
  • 33
  • If you haven't called `get_user()`, why would `some_user` have been set? The subclass init method needs to call the super class's init method, if that is where you are setting it. – Nathaniel Ford Nov 25 '15 at 01:57
  • [This question](http://stackoverflow.com/questions/10840270/python-how-to-get-outer-class-variables-from-inner-static-class) will probably answer yours. – El'endia Starman Nov 25 '15 at 02:00
  • get_user gets called in the on_start functions of the User class. That's not the point of the question. @NathanielFord – Beto Nov 25 '15 at 02:08
  • Any chance you're coming from Java? Python inner classes aren't scoped (and static vs non-static) like Java's. – David Ehrmann Nov 25 '15 at 07:29
  • hahah yep. @DavidEhrmann Are there other ways to access it? – Beto Nov 25 '15 at 07:31

2 Answers2

1

You've not provided all of the code, but the problem may be that get_user() is setting some_user as an instance attribute somewhere, as in self.some_user = foo.

This will only set some_user for that specific instance of User however (so for Bob, Lisa, Beto, User53, etc.), but not for the User class itself. When accessing some_user with self, as in self.some_user, you set it for the specific instance that's executing those statements, not the class. In updating() you're accessing the class attribute User.some_user, not a specific instance attribute like usr53.some_user. In order to update the class attribute, invariant by default for all instances of User, you ought to be setting it with User.some_user = foo in get_user().

Right now in path = "/posts/" + User.some_user, it's trying to access the class attribute which may never have been set. Because nested classes like UpdatingUser can't access the instances of the nesting class (User) that they're called from, UpdatingUser won't be able to access any some_user set with self or any other instance attributes of User. So the solution would be to have get_user() set the class attribute instead of the instance attribute as described in the previous paragraph.

Mathemert
  • 148
  • 3
  • I updated the code. Interesting so a inner class has not access to the parent class variables? I know the way locust starts the class is by running on_start first and that's where I set the variable. But I wasn't sure how to access it once it s ran. – Beto Nov 25 '15 at 07:28
  • @Beto, It does have access to the parent's class variables (in my answer I said attributes instead of variables), but not its instance variables. In the code you posted you're neither setting some_user as a class variable nor an instance variable, but just a variable local in scope to the get_user function. Remember from my answer, setting self.some_user sets an instance variable, setting User.some_user sets the class variable persistent through all instances. When you set some_user outside of any methods like you did on line 2, it's automatically a class variable as if you did User.some_user. – Mathemert Nov 25 '15 at 08:25
0

This answer is a bit late but, if anyone has this issue, the TaskSet has a parent property, which can be used to access the parent's instance variables. The following is what I used for a basic one-time login:

class UserBehaviour(TaskSet):
    def on_start(self):
        self.token = self.login()
        self.headers = {'Authorization': 'Bearer ' + self.token}

    def login(self):
        with self.client.post("/login", catch_response = True) as response:
            return response.json()['token']

    @task
    class UserTask1(TaskSet):
        @task
        def get_data(self):
            self.client.get("/data", headers = self.parent.headers)

class WebsiteUser(HttpLocust):
    task_set = UserBehaviour