Guide de contributions aux exercices Progression

Présentation

Progression est un exerciseur conçu pour aider l’apprentissage de la programmation par la pratique. Il permet d’exécuter, analyser et diagnostiquer du code programmé dans le cadre d’un exercice proposé et génère pour l’étudiant une rétroaction immédiate et spécifique.

Fonctionnement

Les questions

L’unité de base marquant la progression de l’étudiant est la question (souvent aussi désignée par «exercice»). Il s’agit d’une tâche prévue par l’enseignant et devant être réalisée à l’aide d’un algorithme.

Pour chaque question, l’enseignant procure un énoncé et une ébauche de programme pour un ou plusieurs langages de programmation choisis :

Faites un programme qui affiche 3 fois la chaîne de caractères reçue en entrée
chaîne = input()

# Affiche l'entrée
print( chaîne )

L’étudiant a alors la tâche de compléter l’ébauche afin que son programme réponde à l’énoncé.

L’évaluation

La solution de l’étudiant est validée grâce à une batterie de tests prévue par l’enseignant. Pour chaque test, il aura prévu une entrée envoyée sur l’entrée standard de la solution, ainsi qu’un résultat attendu. La sortie de la solution sur la sortie standard doit être identique au résultat attendu pour chacun des tests pour considérer la solution comme valide.

Exemple de tests pour l’exemple précédent :

 -  Test 1
    entrée : Bonjour
    sortie : |
      Bonjour
      Bonjour
      Bonjour

  - Test 2
    entrée : Trois petits tours et puis s'en vont
    sortie : |
      Trois petits tours et puis s'en vont
      Trois petits tours et puis s'en vont
      Trois petits tours et puis s'en vont

Création des questions :

Introduction

Créer une nouvelle question à partager dans Progression est aussi simple que d’écrire un fichier texte et le déposer sur un serveur public, là où Progression pourra le récupérer grâce à son URL.

Chaque question est constituée d’un ou plusieurs fichiers en format YAML et contient un énoncé, une ou plusieurs ébauches de code et un ou plusieurs tests de validation. Le format complet est décrit ici. Un gabarit est aussi disponible pour vos premières questions.

Consultez la source des questions existantes pour des exemples.

Guide de rédaction

Quelques trucs et astuces pour créer les meilleurs questions possibles.

Énoncé

L’énoncé devrait contenir les parties suivantes :

  • mise en contexte
  • description des entrées
  • description des sorties attendues
  • exemples

Pour mieux distinguer ces parties, il est possible de fournir l’énoncé sous forme de liste d’éléments constitué d’un titre et d’un texte qui pourront être rendus sous forme d’onglets ou autre séparation visuelle.

Le gabarit proposé fournit chacune de ces parties.

Nomenclature

Pour uniformiser les termes utilisés dans les énoncés, nous recommandons la nomenclature suivante :

  • Entrée : Les entrées fournies au programme via l’entrée standard.
    • Éviter les termes «saisie au clavier» qui portent à confusion puisque les entrées ne sont pas réellement saisis via un clavier
    • Privilégier «reçu en entrée»
  • Sortie : La sortie textuelle permettant la validation de l’exercice.
    • Éviter «afficher à l’écran» puisque, même si les sorties sont généralement affichées, ce n’est pas toujours le cas.
    • Privilégier «produit en sortie»

Indentation

En général, l’indentation devrait être cohérente avec les parties visibles à l’étudiant. Les parties invisibles ne devraient pas influencer l’indentation.

Par exemple, on peut vouloir rendre invisible la définition d’une classe pour éviter la complexité pour l’étudiant :

class  exec {
         
        public static void main( String  args[] ){
                Scanner sc= new Scanner(System.in);

                // +VISIBLE
                // -TODO
                String mot;
                int répétitions;
                // +TODO

        }

Puisque l’étudiant ne voit pas la partie avant +VISIBLE, l’indentation des déclarations de variables ne lui semblera pas cohérente. On devrait l’ajuster de cette façon :

class  exec {
         
public static void main( String  args[] ){
Scanner sc= new Scanner(System.in);

// +VISIBLE
// -TODO
String mot;
int répétitions;
// +TODO

}

Les tests:

  • Sauf dans les cas les plus simples, au moins 2 tests différents sont nécessaires pour éviter les réponses codées en dur
  • Attention au formattage des nombres décimaux; le formattage par défaut n’est pas constant d’un langage à l’autre
  • Sauf si c’est explicitement l’objectif de la question, éviter les invites de saisie. Si elles sont présentes, elles feront partie de la sortie observée et doivent être prévues dans la sortie attendue.

Cas spécifiques:

  • En Java :
    • Les classes ne doivent pas être déclarées publiques puisqu’il est impossible de spécifier le nom du fichier où elles se trouvent.

Vérifier la question

Le module python progression_qc permet d’effectuer une validation de la syntaxe d’une question.

Installation

Dans un terminal :

pip install progression_qc

Utilisation

python -m progression_qc <chemin du fichier info.yml>

Partage des questions

Formats de question

Une question peut être partagée sous plusieurs formes. Dans tous les cas, la question doit être accessible via un URL public.

Fichier simple

Il s’agit d’un fichier YAML qui peut inclure des références à d’autres fichiers, en autant que tous sont publics et référés par leur URL relatif ou absolu. Exemple:

type: prog
uuid: 6344f538-0ec3-4e3f-8308-fc10d35c6aaf

titre: Bonjour le monde
niveau: Premiers pas

description: Un tout premier programme en Python.

énoncé: !include énoncé.yml  # lien par un URL relatif

ébauches:
    python: !include https://exemple.com/exercices/exec.py # lien par un URL absolu

tests: !include tests.yml

Archive

L’ensemble des fichiers nécessaires à un exercice peut être contenu dans une archive ZIP. Il suffit ensuite de rendre cette archive disponible publiquement et partager son URL.

Dépôt Git

De la même façon, un exercice complet peut être contenu dans un dépôt Git et l’URL à partager est alors le liens HTTPS du dépôt, se terminant par `.git`. Exemple : Pour partager l’exercice Une question unique, il faudrait fournir l’URL : `https://git.dti.crosemont.quebec/progression/contenu/question_unique.git`

Partage par URL

Un simple URL suffit à partager une question avec les utilisateurs. Il suffit de copier et partager l’URL du fichier info.yml ou d’un fichier zip contenant ce fichier et tous les autres fichiers nécessaires. Dans l’interface utilisateur, sélectionnez «Exercices/Ouvrir» et collez l’URL de l’exercice.

ouvrir.png url.png

Par un LMS

Une façon plus commode consiste à utiliser un LMS qui implémente le protocole LTI, tel que Moodle. Il suffit de créer une activité de type « Progression » et fournir un «paramètre personnalisé» src=URL où URL est l’URL du fichier yaml décrivant la question.

Sélection par liens profonds

Dans Moodle ou un autre LMS qui implémente les liens profonds LTI, la fonction de «sélection de contenu» permet de renseigner automatiquement les champs nécessaires à partir d’une banque de question directement dans Progression.

Dans la page de création de l’activité, cliquez sur «Sélectionner un contenu» :

moodle_deeplink.png

pour avoir accès à ses banques de questions dans Progression puis sélectionner celle que l’on désire inclure comme activité :

progression_banque.png

Créer une banque de questions

Pour créer une banque complète de questions, une façon simple est de copier le projet gabarit et y ajouter vos questions.

Ce projet est configuré pour générer la liste de questions à travers un pipeline CI/CD sur Gitlab.

Lier la banque à une instance spécifique de Progression

Par défaut, la liste générée par le pipeline incluera des liens vers l’instance https://progression.crosemont.qc.ca. Les exercices restent utilisables dans n’importe quelle instance, mais le lien direct pourrait ne par diriger vers la bonne instance.

Pour générer les liens vers une autre instance :

  1. Ajoutez une variable «URL_PROGRESSION» dans Gitlab. Dans le menu «Intégration et livraison continue», développez la section VARIABLE et ajoutez une variable CI/CD nommée URL_PROGRESSION qui contient l’URL de votre instanece, par exemple https://progression.crosemont.qc.ca

    variable_cicd.png
  2. Dans la page de votre projet, générez une première liste de questions :
    1. Dans le menu «Intégration et livraison continue» ou «CI/CD», cliquez sur «Pipelines», «Run pipeline» et le bouton «Run pipeline» en bas.
    2. La liste des questions sera créée à l’adresse donnée dans «Exploitation / Pages» ou «Deployments / Pages», selon le modèle https://<nom d'utilisateur>.gitlab.io/<projet>
    3. Par la suite, la liste sera automatiquement recrée à chaque modification du projet pour réfléter les changements.

Ajouter une banque à ses favoris

Dans Progression, il est possible de se constituer une liste de banques de questions favorites. Dans le menu «Exercices / Banques», il suffit d’ajouter un item en spécifiant un nom et un URL. L’URL à utiliser est celui du fichier `contenu.yml` à la racine du site statique généré automatiquement par le pipeline CI / CD. Par exemple, pour la liste de questions Les fondements de la programmation, l’URL de la banque est `https://progression.pages.dti.crosemont.quebec/contenu/prog_1/contenu.yml`.

nouvelle_banque.png

Un lien est disponible à même la liste de question pour ajouter une banque à Progression :

ajouter_une_banque.png

Partage de questions

N’importe quel service permettant de partager des fichiers publiquement permettent d’héberger les exercices Progression:

Une forge Git

  1. Partager grâce à Gitlab, Github, Bitbucket, etc. : Peut-être la solution la plus simple. Déposez les fichiers dans un dépôt public sur un de ces services et partagez le lien «raw» du fichier info.yml

    • Github.: github_raw.png
    • Gitlab.: gitlab_raw.png

    Par exemple, dans une activité Progression de Moodle, placez dans les paramètres personnalisés l’url src=https://gitlab.com/projet-progression/contenu/prog_1/-/raw/master/questions/01_declarations/01_syntaxe_declarations/1_typage_1/info.yml

  2. Sur Gitlab, utilisez le gabarit de dépôt avec CI/CD

Nextcloud

Placez le fichier info.yml et ses fichiers «inclus» dans une archive zip et déposez-la sur Nextcloud. Récupérez le lien de partage, ajoutez /download à la fin et c’est ce que vous devez placer dans votre activité Moodle. Exemple : Dans Moodle (paramètres personnalisés ) : src=https://panoramix.dti.crosemont.quebec/s/Zw24eY6n6b9yASR/download

Dropbox

Placez le fichier info.yml et ses fichiers «inclus» dans une archive zip et déposez-la sur Nextcloud. Récupérez le lien de partage, remplacez dl=0 par dl=1 à la fin et c’est ce que vous devez placer dans votre activité Moodle. Exemple : Dans Moodle (paramètres personnalisés ) : src=https://www.dropbox.com/s/bdqrgfzo4ts5msl/boucle_simple.zip?dl=1

Problèmes rencontrés

À la validation

expected <block end>, but found ’<scalar>’

  • Problème

    progression_qc signale l’erreur :

    expected <block end>, but found '<scalar>'

  • Explication

    L’indentation d’un bloc commençant par | ou > est déduite de la première ligne. Dans les cas où l’indentation d’un bloc change de droite à gauche, cette erreur survient.

  • Solution

    Forcer l’indentation par |n ou >n où n est le nombre d’espace d’indentation par rapport au début du bloc :

    • Exemple
          sortie: |2
               a   
              aaa  
             aaaaa 
            aaaaaaa
      

      La véritable indentation du bloc commence à 2 caractères du mot «sortie», mais la première ligne commence au caractère 5.

À l’exécution en ligne

Error: Request failed with status code 502

  • Problème

    Progression signale l’erreur :

    Error: Request failed with status code 502

  • Explication

    La question ne peut pas être chargée.

    Problèmes possibles :

    • L’URL de la source est incorrecte
    • Le fichier info.yml est inaccessible
    • Un des fichiers inclus par info.yml est inaccessible par son nom Les liens de partage (par exemple sur Google Drive ou Dropbox) permettent de partager un fichier unique (info.yml), mais pas les fichiers inclus.
  • Solutions
    • Placer toute la question dans un seul fichier, sans inclusion.
    • Inclure les fichiers grâce à leur URL public
    • Utiliser un mode de partage qui permet l’accès public par nom