Testing questions that use random in Python3

Testing questions that use random in Python3

by Stef Goff -
Number of replies: 3

How can I set up a test to allow me to save a very basic question that asks the user to output a randomly generated number between 1 and 100.

Currently it won't save because there is no test case because I would have to guess the random number for the expected output box.

I had figured to test for the presence of random.randint(1,101) in the string of the student answer to check it was done correctly but can't figure how to tell it the expected output should be whatever is randomly generated. Any tips on how to get round this would be much appreciated. It's in its infancy at my school but the transition to CodeRunner delivery of Python3 learning is pretty exciting and the more I can do to develop good effective questions the faster we can integrate it.

In reply to Stef Goff

Re: Testing questions that use random in Python3

by Jenny Harlow -

I do something like this (using Matlab not Python), but I don't look for particular featueres in the student answer.  I use a template grader (see the CodeRunner documentation) which runs both the student answer and the 'model answer' and compares the outputs from each of these for marking.  My template grader adds code before the answer code (student, model) to set the prng state. 

That is a short description that covers a lot of complexity! I spent a bit of time building up to it.  I do not think it would have been worth it just for the sake of being able to ask 'generate a random number' questions, but our course (which is more 'coding for engineers' than 'programming') had a lot of particular needs that meant that I had to write a template grader that ran both student answer and model answer anyway. 

You may be able to get at something close to what you want to assess without the full CodeRunner setup in this case.  Overall I feel very strongly that when we want to assess students' ability to write code the best way to do that is to get them to write code, but sometimes it takes a lot of additional work to assess something that is not in itself an absolutely core skill.   I use the fact that I can mix a few non-CodeRunner questions (using other Moodle question types) into a Moodle quiz to give me a bit of flexibility. 

It might be worth considering whether you could use (say) a multiple choice question (like "which of the following could you use to ...") as a stopgap to cover random number generation while you build up to writing template graders.  You could mix that in with CodeRunner questions that tackle things that the existing built-in question types assess well. 

One final comment on assessing by looking for particular things in the student code.  That in itself can get quite complicated (you have to consider the different ways they could achieve the same end, use of variables or hard-coded inputs, whitespace...) and in some ways it may go away from the idea of students writing code that is run to see if it actually does what is required. 

This is all based on my own experience and I may be missing something really important or useful.

Jenny

In reply to Stef Goff

Re: Testing questions that use random in Python3

by Ian Currie -

I'm just starting out with Coderunner so I don't know if this is the best way but I'd recommend making use of random.seed.
I used it in a question with my students where they had to roll a die that had between two and up to twenty sides.
In the test case I used seed and generated a list of random rolls and then compared it with the students response using the same seed.

Template params

{ "diceRollFunctionName": "{{ random(["roll", "diceRoll", "dieRoll", "rollDice",  "rollDie", "rollADice", "rollADie", "dice_roll", "die_roll", "roll_dice",  "roll_die", "roll_a_dice", "roll_a_die" ]) }}",
"diceSides": {{ 2 + random(18) }}
}


Question Text

{{ STUDENT.firstname }}, write a function with the identifier {{ diceRollFunctionName }}.
The function should roll a {{diceSides}} sided die and return the result.
You will need to import the random library for this function to work.
It is recommended that you use randint for this task.
Test Case
expectedResults = []
studentResults = []

random.seed(0)
for i in range(0,100):
    expectedResults.append(random.randint(1,{{diceSides}}))

random.seed(0)
for i in range(0,100):
    studentResults.append({{diceRollFunctionName}}())

print(expectedResults == studentResults)
Test Case Expected Answer
True
 Answer

import random
def {{ diceRollFunctionName }}():
    result = random.randint(1, {{diceSides}})
    return result


In reply to Stef Goff

Re: Testing questions that use random in Python3

by Ian Currie -

Here is a simplified test case that should work for your particular question (assuming that the students writes a sub-function called randomNumberGenerator)

expectedResults = []
studentResults = []
random.seed(0)
for i in range(0,100):
    expectedResults.append(random.randint(1,100))
random.seed(0)
for i in range(0,100):
    studentResults.append(randomNumberGenerator())
print(expectedResults == studentResults)