Valide_digitaal_toetsen

In this situation of the Corona crisis and students who do schoolwork from home, many teachers are looking for valid ways to test students. The longer this home working situation lasts, the more this will be necessary to measure the students' progress. However, students will be inclined to "help" each other during the test, so that the test does not really provide a good measurement. A possible solution is to automatically create a different version of the test for each student. For example, it is not possible to share answers with each other.

Please note, this way of testing works especially for courses, where the answers have to be calculated, devised or composed and cannot be taken directly from the book.

HandiHow has experimented with a possible solution within Google forms. This is popular with many schools because a Google environment is used, and tests in the form of a Google form can be turned off via Google Classroom.

Tutorial: digital tests in Google forms

Pay attention! Some programming knowledge of Javascript is required to follow this tutorial. It does take a little time, but in the end you have little check-up work, because the answers are automatically checked in the Google form. So it may be worth doing this. Also because you can use the test for years. In addition, once you have a good script for your section, you can quickly take a new test by adjusting only the questions for each topic or grade. So you can apply it over and over again.

The strategy is as follows:

  • We first create a form that collects general information from the students
  • We can automatically collect email addresses and also set this form to be submitted only once per student
  • Submitting this form will run an automatic script
  • In this script a Google quiz is made, specifically for the student in question. The link to this quiz will be sent to the student by email
  • The student therefore automatically gets his own version of the test and can then take it and submit it
  • The teacher can find all forms in his Google Drive, with the name and class of the student listed as the file name

Benefits:

  • Each student gets their own version of the test, so there is no possibility to share answers
  • A lot of wrong answers are automatically made, so betting on an answer yields a low grade
  • The work is automatically checked so there is no review work

Cons:

  • Each student has their own form, so you do not get an overview of the class
  • The forms must be manually checked afterwards to make an overview of all grades

Step 1. Create the registration form

We first create a registration form (Google Form). We set that email addresses are collected and that respondents may only submit 1 answer (otherwise the student can request multiple tests).

We set the following confirmation message at “Presentation”:

"Thanks for registering. You will receive the link to the test by email. ” is.

We now create some mandatory fields in the form:

  • Email (this field is automatically created by Google Forms if you set “Collect email addresses”)
  • Name - question type is short answer text - set to mandatory
  • Class - question type is multiple choice - set to mandatory - options are eg “3A”, “3B”, “3C”

Step 2. Open the spreadsheet that comes with the registration form

Now go to the “Answers” ​​tab and click on the Google Sheets icon in the top right corner.

Create a new spreadsheet. The name is filled in automatically.

You now open the spreadsheet by clicking on “Create”.

You now go to the “Tools” menu and then click on “Script Editor”.

We will now work on a script that will run automatically every time a student has registered for the test.

This script is responsible for creating a new Google form, with the specific version of this test for this student.

Javascript is required to create this script.

We are now creating a function that will edit the forms.

Step 3. Set the script's resources and trigger

We first save the project under its own name.

We call this project “Test version email to student”.

//note due to translation issues you may need to change the strings behind values[] to your own language

function onFormSubmit(e) {
  //get the variables from the inital form submission
  var values = e.namedValues;
  var email = values['E-mailadres'];
  var name = values['Naam'];
  var classroom = values['Klas'];
  
  Logger.log(values);
}

We rename the function “myFunction” and now call this function “onFormSubmit (e)”.

From the variable “e” we can get the information of the submitted form.

This way we get the student's email address, name and class. You can see the logger by clicking Cmd + Enter.

Now set up “Resources” and go to “Advanced Google Services”.

You check the options for “Drive API” and “Gmail API”.

Go to the “Edit” menu and click on “Triggers for your current project”.

There is also a small icon with a clock. This way you can also go there directly.

Set to run the “onFormSubmit” function with the appointment source “From spreadsheet” and the event type “When submitting form”.

Set up to be notified immediately if the function execution fails. This allows you to respond quickly if a student does not receive the test (in case of error in processing).

You can now try whether the trigger has been set successfully. You fill in the registration form and then open the logger.

If all goes well, you will not receive an email with error messages, and you will see in the logger the email address, name and class you just entered. Now we can continue taking the test.

Step 4. Automatically create a new version of the test

We are now creating a function that takes the quiz. As input to this function we have the name and class of the student. This way we can save the form with the file name including name and class. This happens after the comment “create the form”.

Then we set the form to Quiz. We define a number of random variables. We also make arrays with the correct unit and then two more incorrect units. We will use the variables and the lists of units to calculate the correct answer, but also to generate a large number of incorrect answers with sometimes incorrect units.

We also create an array of questions, in which we define some settings such as the title of the question, the calculation of the correct answer, the units array that applies to this answer, the number of points the question yields, and the number of wrong answers to be made automatically with the question.

Finally, we put in the return statement that the function must return the “publishedUrl” string. We will then email this to the student.

function createForm(name, classroom) {
  //create the form
  var form = FormApp.create('Toets remmen en botsen - ' + name + ' - ' + classroom);
  
  form
  .setIsQuiz(true)
  .setLimitOneResponsePerUser(true)
  .setCollectEmail(true)
  .setRequireLogin(true)
  .setPublishingSummary(true);
  
  //create random initialization variables
  var massCar = getRandomInt(1000, 2500); //mass in kg
  var massDriver = getRandomInt(60, 100); //mass in kg
  var speedCar = getRandomInt(20, 40); //speed in m/s
  var breakingTime = getRandomInt(4, 8); //time it takes to stop the car in s
  var breakingForceCar = getRandomInt(2500,5000); //breaking force in Newton
  var reactionTime = getRandomInt(5,10) / 10; //reaction time in seconds
  var crashingTime = getRandomInt(10,20) / 100; //crashing time in seconds
  
  //create arrays with the correct unit of measure in the first element and some wrong units in the second and third element
  var accelerationUnits = ['m/s2', 'm/s', 'm'];
  var velocityUnits = ['m/s', 'm/s2', 'm'];
  var forceUnits = ['N', 'Pa', 'm/s'];
  var locationUnits = ['m', '', 'm/s'];
  var timeUnits = ['s', 'm', 'm/s']
  
  //create all questions
  var questions = [
    {
      question: 'Een auto rijdt met een snelheid van ' + speedCar + ' m/s. De auto stopt in ' + breakingTime + ' seconden. Bereken de vertraging van de auto.',
      answer: speedCar / breakingTime,
      unitArray: accelerationUnits,
      points: 3,
      wrongAnswers: 9
    },
    {
      question: 'De auto heeft een massa van ' + massCar + ' kg. Bereken de remkracht op de auto terwijl de auto stopt. Gebruik dezelfde gegevens uit de vorige opgave hiervoor.',
      answer: speedCar / breakingTime * massCar,
      unitArray: forceUnits,
      points: 2,
      wrongAnswers: 9
    },
    {
      question: 'Bereken de stopafstand van de auto. Gebruik weer dezelfde gegevens uit opgave 1 hiervoor.',
      answer: speedCar / 2 * breakingTime,
      unitArray: locationUnits,
      points: 2,
      wrongAnswers: 9
    },
    {
      question: 'De auto gaat weer optrekken. Zijn snelheid is daarna wederom ' + speedCar + 
      ' m/s. Dan ziet de bestuurder een konijn. Zijn reactietijd is ' + reactionTime + ' seconde. Bereken de reactie-afstand.',
      answer: speedCar * reactionTime,
      unitArray: locationUnits,
      points: 2,
      wrongAnswers: 9
    },
    {
      question: 'Het konijn kwam de weg op toen hij nog een afstand had van 150 meter van de auto. ' + 
      ' Bereken hoe snel de auto moet afremmen - na de reactietijd - om tot stilstand te komen en het konijn net niet plat te rijden',
      answer: (150 - speedCar * reactionTime) / speedCar / 2 ,
      unitArray: timeUnits,
      points: 4,
      wrongAnswers: 9
    },
    {
      question: 'Het is gelukkig goed afgelopen met het konijn. Hij kon op tijd van de weg springen. De auto trekt weer op en heeft ' + 
      'dan weer een snelheid van ' + speedCar + ' m/s. Na een tijdje krijgt de auto een klapband en botst hij tegen een boom. ' +
      'Door de kreukelzone vertraagt de auto eenparig en staat hij na ' + crashingTime + ' seconde stil. Bereken de vertraging. ',
      answer: speedCar / crashingTime,
      unitArray: accelerationUnits,
      points: 3,
      wrongAnswers: 9
    },
    {
      question: 'De bestuurder van de auto heeft een massa van ' + massDriver + ' kg. Bereken de kracht op de veiligheidsgordel van de bestuurder tijdens de botsing.',
      answer: speedCar / crashingTime * massDriver,
      unitArray: forceUnits,
      points: 2,
      wrongAnswers: 9
    }
  ];
  questions.forEach(question => {
     createMultipleChoiceItem(form, question.question, question.answer, question.unitArray, question.points, question.wrongAnswers);
  })
  
  return form.getPublishedUrl();
}

We define the function that makes a multiple choice question.

function createMultipleChoiceItem(form, title, correctAnswer, unitArray, points, numberOfWrongChoices){
  var item = form.addMultipleChoiceItem();
  //generate all the question choices
  var correctAnswerString = roundOneDecimal(correctAnswer).toString() + ' ' + unitArray[0];
  var choices = [item.createChoice(correctAnswerString, true)]
  for (let step = 0; step < numberOfWrongChoices; step++) {
    choices.push(item.createChoice(generateRandomWrongChoiceString(correctAnswer, unitArray), false))
  }
  //now set all properties on the question
  item
  .setTitle(title)
  .setChoices(choices.sort(() => Math.random() - 0.5))
  .setPoints(points)
  .setFeedbackForCorrect(FormApp.createFeedback()
                         .setText('Dit is het juiste antwoord! Goed gedaan.').build())
  .setFeedbackForIncorrect(FormApp.createFeedback()
                         .setText('Dit is niet het goede antwoord. Het juiste antwoord is ' + correctAnswerString).build())
  .showOtherOption(false)
  .setRequired(true);
  
}

And a few more helper functions.

function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min + 1)) + min;
}

function roundOneDecimal(number) {
  return Math.round(number * 10) / 10
}

function generateRandomWrongChoiceString(correctAnswer, unitArray){
  return roundOneDecimal(correctAnswer * Math.random())  + ' ' + unitArray[getRandomInt(0,2)]
}

Step 5. Customize the onFormSubmit function

We still have to adjust the “onFormSubmit” function, so that this function always creates a new version of the test and sends the link by email to the student. For this we use the “createForm” function we created earlier. We construct an HTML body for the email with this link in it.

GmailApp.sendEmail (…) can then be used to send the email. See the custom function below.

function onFormSubmit(e) {
  //get the variables from the inital form submission
  var values = e.namedValues;
  var email = values['E-mailadres'];
  var name = values['Naam'];
  var classroom = values['Klas'];
  
  Logger.log(values);
  //create the quiz in Google Forms and get the published Url
  var publishedUrl = createForm(name,classroom);
  
  //construct the email to the student
  var htmlBody = '<p>Beste ' + name + '</p>';
  htmlBody += '<p>Je kunt jouw toets nu beginnen door op de onderstaande link te klikken. Veel succes!</p>';
  htmlBody += "<a href=\"" + publishedUrl + "\">Link naar jouw persoonlijke test</a>";

  GmailApp.sendEmail(email, 'Toets remmen en botsen', '', {htmlBody: htmlBody})
  
}

Now check if everything is going well! Fill in the registration form again and take the quiz. Also check if you can find the test in your Google Drive!

Good luck with tests.

Do you have questions about this or do you need help with making such digital tests? Feel free to come in contact with HandiHow.