From d1f84af308962682b326231315dd44a31722d1fd Mon Sep 17 00:00:00 2001 From: Harman-Aalto Date: Tue, 28 Jan 2025 10:04:18 +0200 Subject: [PATCH] Create GitHub workflow to automatically run tests #64 -Added Dolos as submodule -Modified how to compare matches: -Created a new Django command 'recompare' to compare matches without using the "Recompare all" or the "Recompare all exercises with unmatched submissions" button -In exercise settings "Recomparing all submissions" now recompares without needing the CLI command 'matchsubmissions' -In course page "Recompare all exercises with unmatched submissions" now recompares without needing the CLI command 'matchsubmissions' -Added Python submissions for testing Radar -Updated README.md for how to compare matches --- .github/workflows/tests.yml | 52 +++++++++++++++++++ .gitmodules | 3 ++ data/management/commands/recompare.py | 20 +++++++ dolos | 1 + e2e_tests/README.md | 17 +++--- .../A/ex2/1_file1_submission1 | 10 ++++ .../B/ex2/2_file1_submission2 | 12 +++++ .../C/ex2/3_file1_submission2 | 11 ++++ .../D/ex2/4_file1_submission1 | 8 +++ .../E/ex2/5_file1_submission2 | 9 ++++ .../F/ex2/6_file1_submission1 | 10 ++++ provider/filesystem.py | 8 ++- 12 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/tests.yml create mode 100644 .gitmodules create mode 100644 data/management/commands/recompare.py create mode 160000 dolos create mode 100644 e2e_tests/testing_data/radar_test_python/A/ex2/1_file1_submission1 create mode 100644 e2e_tests/testing_data/radar_test_python/B/ex2/2_file1_submission2 create mode 100644 e2e_tests/testing_data/radar_test_python/C/ex2/3_file1_submission2 create mode 100644 e2e_tests/testing_data/radar_test_python/D/ex2/4_file1_submission1 create mode 100644 e2e_tests/testing_data/radar_test_python/E/ex2/5_file1_submission2 create mode 100644 e2e_tests/testing_data/radar_test_python/F/ex2/6_file1_submission1 diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..498d06f --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,52 @@ +name: tests +on: + # trigger when pushed to any branch (for development) + push: + # trigger when a pull request is made to master + pull_request: + branches: + - master +jobs: + playwright-tests: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.10' + - name: Start Dolos + working-directory: dolos + run: | + docker pull ghcr.io/dodona-edu/dolos-cli:latest + docker compose up --detach + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + - name: Ensure browsers are installed + run: python -m playwright install --with-deps + - name: Set up Radar + run: | + python manage.py migrate + DJANGO_SUPERUSER_PASSWORD=Password \ + python manage.py createsuperuser \ + --no-input \ + --username=Username \ + --email=Username@email.com + - name: Upload submissions and compare + run: | + bash run_loadsubmissions.sh e2e_tests/testing_data/radar_test_python testcourse exercise1 1 + python manage.py recompare testcourse/exercise1 + - name: Run Radar + run: python manage.py runserver & + - name: Run tests + run: pytest --tracing=retain-on-failure + - uses: actions/upload-artifact@v4 + if: ${{ !cancelled() }} + with: + name: playwright-traces + path: test_results/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9a500b9 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dolos"] + path = dolos + url = https://github.com/dodona-edu/dolos diff --git a/data/management/commands/recompare.py b/data/management/commands/recompare.py new file mode 100644 index 0000000..dc7d4e2 --- /dev/null +++ b/data/management/commands/recompare.py @@ -0,0 +1,20 @@ +from django.core.management.base import BaseCommand + +from provider.filesystem import recompare +from data.models import Course + + +class Command(BaseCommand): + help = ( + "Calculate similarity for all submissions in the exercise." + ) + + def add_arguments(self, parser): + parser.add_argument('course/exercise', type=str) + + def handle(self, *args, **options): + (course_key, exercise_key) = options['course/exercise'].split("/", 1) + course = Course.objects.get(key=course_key) + exercise = course.get_exercise(exercise_key) + + recompare(exercise, {}) diff --git a/dolos b/dolos new file mode 160000 index 0000000..19eb688 --- /dev/null +++ b/dolos @@ -0,0 +1 @@ +Subproject commit 19eb6881ce8931e102332aeaea2dcbed737c3b2d diff --git a/e2e_tests/README.md b/e2e_tests/README.md index f9bcb50..eee1599 100644 --- a/e2e_tests/README.md +++ b/e2e_tests/README.md @@ -2,7 +2,7 @@ This document provides a guide to create and run end-to-end tests for Radar using [Playwright](https://playwright.dev/python/). -## Set up environment +## Run Radar Make sure everything is set up following this [Radar development guide](https://github.com/apluslms/radar/blob/master/doc/DEVELOPMENT.md) before continuing. @@ -17,22 +17,19 @@ Make sure everything is set up following this [Radar development guide](https:// 4. Load submissions: `./run_loadsubmissions.sh ${directory_with_submissions} {course} {exercise} 1` -5. In a browser navigate to: `http://localhost:8000/{course}/{exercise}/settings/` - * Press the "Recompare all" button +5. Match submissions: ` python manage.py recompare {course}/{exercise}` -6. Match submissions: `python manage.py matchsubmissions {course}/{exercise}` - -## Set up Dolos +## Run Dolos Dolos is required for `test_dolos` in `e2e_tests/test_dolos.py`. -1. Clone the [Dolos](https://github.com/dodona-edu/dolos) repository +Launch Docker daemon if Docker is not running: ` sudo dockerd` -2. Launch Docker daemon: `dockerd` +1. Change to Dolos directory: `cd dolos` -3. In a new terminal at the root of the Dolos repository run: `docker compose up` +2. Run Dolos: `docker compose up` -Now Dolos should be running in a separate window and work with Radar. +Now Dolos should be running in a separate window and works with Radar. ## Create tests diff --git a/e2e_tests/testing_data/radar_test_python/A/ex2/1_file1_submission1 b/e2e_tests/testing_data/radar_test_python/A/ex2/1_file1_submission1 new file mode 100644 index 0000000..6e342fb --- /dev/null +++ b/e2e_tests/testing_data/radar_test_python/A/ex2/1_file1_submission1 @@ -0,0 +1,10 @@ +import random + +def print_hello(): + print('Hello, World!') + +def main(): + print_hello() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/e2e_tests/testing_data/radar_test_python/B/ex2/2_file1_submission2 b/e2e_tests/testing_data/radar_test_python/B/ex2/2_file1_submission2 new file mode 100644 index 0000000..2f46115 --- /dev/null +++ b/e2e_tests/testing_data/radar_test_python/B/ex2/2_file1_submission2 @@ -0,0 +1,12 @@ +import random +import math +import datetime + +def print_hello(): + print('Hello, World!') + +def main(): + print_hello() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/e2e_tests/testing_data/radar_test_python/C/ex2/3_file1_submission2 b/e2e_tests/testing_data/radar_test_python/C/ex2/3_file1_submission2 new file mode 100644 index 0000000..7c85898 --- /dev/null +++ b/e2e_tests/testing_data/radar_test_python/C/ex2/3_file1_submission2 @@ -0,0 +1,11 @@ +import datetime +import random + +def print_hello(): + print('Hello, World!') + +def main(): + print_hello() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/e2e_tests/testing_data/radar_test_python/D/ex2/4_file1_submission1 b/e2e_tests/testing_data/radar_test_python/D/ex2/4_file1_submission1 new file mode 100644 index 0000000..335408b --- /dev/null +++ b/e2e_tests/testing_data/radar_test_python/D/ex2/4_file1_submission1 @@ -0,0 +1,8 @@ +import random +import math + +def add(a, b): + return a + b + +if __name__ == '__main__': + print(add(1, 2)) \ No newline at end of file diff --git a/e2e_tests/testing_data/radar_test_python/E/ex2/5_file1_submission2 b/e2e_tests/testing_data/radar_test_python/E/ex2/5_file1_submission2 new file mode 100644 index 0000000..14dfcc2 --- /dev/null +++ b/e2e_tests/testing_data/radar_test_python/E/ex2/5_file1_submission2 @@ -0,0 +1,9 @@ +import math +import datetime +import random + +def print_random_number(): + print(f'Random number: {random.randint(1, 100)}') + +if __name__ == '__main__': + print_random_number() \ No newline at end of file diff --git a/e2e_tests/testing_data/radar_test_python/F/ex2/6_file1_submission1 b/e2e_tests/testing_data/radar_test_python/F/ex2/6_file1_submission1 new file mode 100644 index 0000000..6e342fb --- /dev/null +++ b/e2e_tests/testing_data/radar_test_python/F/ex2/6_file1_submission1 @@ -0,0 +1,10 @@ +import random + +def print_hello(): + print('Hello, World!') + +def main(): + print_hello() + +if __name__ == '__main__': + main() \ No newline at end of file diff --git a/provider/filesystem.py b/provider/filesystem.py index d4273ce..ae6e21e 100644 --- a/provider/filesystem.py +++ b/provider/filesystem.py @@ -5,6 +5,8 @@ from radar.config import tokenizer_config from provider.insert import submission_exists, insert_submission, prepare_submission from provider import tasks +from matcher.tasks import match_exercise +from radar.settings import DEBUG logger = logging.getLogger("radar.provider") @@ -62,8 +64,10 @@ def recompare(exercise, config): exercise.course.save() exercise.clear_all_matches() exercise.touch_all_timestamps() - # Matching proceeds with CLI command - # matcher_tasks.match_exercise(exercise.id) + if DEBUG: + match_exercise(exercise.pk, False) + # Else matching proceeds with CLI command + # matcher_tasks.match_exercise(exercise.id) def recompare_all_unmatched(course):