The constructor for the Scenario class accepts two arguments: a description and a dictionary for URLs. As mentioned earlier, each task has a URL (or URLs) associated with it. By setting a URL for a scenario, you cause all tasks added to that particular task to have the same URL. Simce the tasks by themselves do not have any previously defined URLs, we need to make sure that the supplied dictionary is not empty. The constructor also initializes a list called tasks which of course, maintains a list of tasks.
The addTask() method lets you add a Task to a Scenario. First we check to see if the object passed in implements the setUrlDict() method. If it doesn't we raise an exception. If it does implement the method, we check to see whether the current instance of the Scenario class has a non-empty urlDict dictionary. If it does, we go ahead and set the task's urlDict property to the same value. As a side note, Python doesn't have explicit interfaces. The language has implied interfaces. Hence, we need to inspect the object at runtime to see whether it implements a necessary method.
The next if-statement checks to see whether the supplied object implements the initializeTask() method. If it does, we go ahead and run that method.
Finally, we check to see if the supplied object implements the run() method, since it makes no sense to add a task that we cannot run. If it does, we add it to our list of tasks.
The class has two accessor methods: getUrl() and getUrlDict() which perform the same functions as the Task base classes's getUrl() and getUrlDict() methods.
You might be wondering why the mutator methods don't actually let you change anything. The reason is because all the child tasks of a Scenario must have the same URL. As you can see, we initialize the URL of a task only when it is added. If you were allowed to change the URL of a Scenario later, then the tasks wouldn't have the same URL as the scenario. Of course, you could then say that in the setUrlDict() or setUrl() methods we just need to update all the tasks with the new URL. But that would be a side-effect, and side-effects are not good! Finally, there simply is no reason to change the URL of a Scenario during runtime. Since the tests themselves are tied to a task, and therefore to a scenario, altering the URL of a scenario while the test is running would make your statistics meaningless.
The run() method iterates through all the tasks belonging to this scenario.
Now that we've gone over the building blocks of the framework, let's use them to create a scenario that we want to test.