-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #63 from Harman-Aalto/Create-Test
Create Playwright E2E tests
- Loading branch information
Showing
8 changed files
with
213 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Radar Testing Guide | ||
|
||
This document provides a guide to create and run end-to-end tests for Radar using [Playwright](https://playwright.dev/python/). | ||
|
||
## Set up environment | ||
|
||
Make sure everything is set up following this [Radar development guide](https://github.com/apluslms/radar/blob/master/doc/DEVELOPMENT.md) before continuing. | ||
|
||
1. Run Python environment: `source py_venv/bin/activate` | ||
|
||
2. Before testing create super user using: `python manage.py createsuperuser`<br> | ||
Username: `Username`<br> | ||
Email: `[email protected]`<br> | ||
Password: `Password`<br> | ||
|
||
3. Run server: `python manage.py runserver` | ||
|
||
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 | ||
|
||
6. Match submissions: `python manage.py matchsubmissions {course}/{exercise}` | ||
|
||
## Set up Dolos | ||
|
||
Dolos is required for `test_dolos` in `e2e_tests/test_dolos.py`. | ||
|
||
1. Clone the [Dolos](https://github.com/dodona-edu/dolos) repository | ||
|
||
2. Launch Docker daemon: `dockerd` | ||
|
||
3. In a new terminal at the root of the Dolos repository run: `docker compose up` | ||
|
||
Now Dolos should be running in a separate window and work with Radar. | ||
|
||
## Create tests | ||
|
||
1. Open new terminal. | ||
|
||
2. Run Python environment: `source py_venv/bin/activate` | ||
|
||
3. Record tests: `playwright codegen --target python-pytest "localhost:8000"` | ||
|
||
4. Copy generated code into a Python file. | ||
|
||
[Generating tests](https://playwright.dev/python/docs/codegen-intro) | ||
|
||
[Writing tests](https://playwright.dev/python/docs/writing-tests) | ||
|
||
## Run and debug tests | ||
|
||
Run all tests: `pytest` | ||
|
||
Run and debug a specific test: `PWDEBUG=1 pytest -s -k <test_method_name>` | ||
|
||
[Running and debugging tests](https://playwright.dev/python/docs/running-tests) |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# Imports | ||
from playwright.sync_api import Page, expect | ||
|
||
# Function to login | ||
def login(page: Page) -> None: | ||
page.goto('http://localhost:8000/') | ||
page.get_by_label('Username').click() | ||
page.get_by_label('Username').fill('Username') | ||
page.get_by_label('Password').click() | ||
page.get_by_label('Password').fill('Password') | ||
page.get_by_role('link', name='Hide »').click() | ||
page.get_by_role('button', name='Login').click() | ||
page.locator('td > a').first.click() | ||
|
||
# Function to save settings and navigate back | ||
def save_and_navigate_back(page: Page) -> None: | ||
page.locator('button[name=\'save\']').click() | ||
page.locator('.breadcrumb > li:nth-child(2)').click() | ||
|
||
#Function to change exercise value and check if it was changed | ||
def change_value(page: Page, value_to_change: str, exercise_value: str, contain_text: str = '') -> None: | ||
page.get_by_role('link', name=' Settings').first.click() | ||
page.get_by_label(value_to_change).click() | ||
page.get_by_label(value_to_change).fill(exercise_value) | ||
save_and_navigate_back(page) | ||
expect(page.locator('tbody')).to_contain_text(f'{exercise_value}{contain_text}') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Imports | ||
from playwright.sync_api import Page, expect | ||
from e2e_tests.helpers import login | ||
|
||
# Test to check if Dolos is generating the plagiarism report | ||
def test_dolos(page: Page) -> None: | ||
login(page) | ||
page.locator('td > a').first.click() | ||
page.locator('#dolos-filter').select_option('all') | ||
page.get_by_role('link', name='Run analysis').click() | ||
expect(page.get_by_text('Source code plagiarism')).to_be_visible(timeout=25000) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Imports | ||
import re | ||
from playwright.sync_api import Page, expect | ||
from random import randrange | ||
from e2e_tests.helpers import login, save_and_navigate_back, change_value | ||
|
||
# Test login | ||
def test_login(page: Page) -> None: | ||
login(page) | ||
expect(page.get_by_role('button', name='Logout')).to_be_visible() | ||
|
||
# Test logout | ||
def test_logout(page: Page) -> None: | ||
login(page) | ||
page.get_by_role('button', name='Logout').click() | ||
expect(page.get_by_text('Username')).to_be_visible() | ||
expect(page.get_by_text('Password')).to_be_visible() | ||
|
||
# Test change exercise name | ||
def test_change_exercise_name(page: Page) -> None: | ||
exercise_num = randrange(9) + 1 | ||
login(page) | ||
current_exercise_name = page.locator('td > a').first.inner_text() | ||
change_value(page, 'Name', f'exercise{exercise_num}') | ||
change_value(page, 'Name', f'{current_exercise_name}') | ||
|
||
# Test change exercise tokenizer | ||
def test_change_tokenizer(page: Page) -> None: | ||
tokenizers = [ | ||
("skip", "Skip"), | ||
("scala", "Scala"), | ||
("python", "Python"), | ||
("js", "JavaScript (ECMA 2016)"), | ||
("html", "HTML5"), | ||
("css", "CSS"), | ||
] | ||
|
||
login(page) | ||
page.get_by_role('link', name=' Settings').first.click() | ||
|
||
current_tokenizer = page.locator('#id_tokenizer').input_value() | ||
current_tokenizer_index = [x for x, y in enumerate(tokenizers) if y[0] == current_tokenizer][0] | ||
new_tokenizer_index = randrange(len(tokenizers)) | ||
while current_tokenizer_index == new_tokenizer_index: | ||
new_tokenizer_index = randrange(len(tokenizers)) | ||
|
||
page.get_by_label('Tokenizer type').select_option(index=new_tokenizer_index) | ||
save_and_navigate_back(page) | ||
expect(page.locator('tbody')).to_contain_text(tokenizers[new_tokenizer_index][1]) | ||
page.get_by_role('link', name=' Settings').first.click() | ||
page.get_by_label('Tokenizer type').select_option(index=current_tokenizer_index) | ||
save_and_navigate_back(page) | ||
expect(page.locator('tbody')).to_contain_text(tokenizers[current_tokenizer_index][1]) | ||
|
||
# Test change exercise minimum match tokens | ||
def test_change_minimum_match_tokens(page: Page) -> None: | ||
min_tokens = randrange(8) + 3 | ||
login(page) | ||
current_min_tokens = int(page.locator('tr > td:nth-child(9)').first.inner_text().split(' ')[0]) | ||
change_value(page, 'Minimum match tokens', f'{min_tokens}') | ||
change_value(page, 'Minimum match tokens', f'{current_min_tokens}', ' tokens') | ||
|
||
# Test visibility of histogram and grid | ||
def test_similarity_visibility(page: Page) -> None: | ||
login(page) | ||
page.locator('td > a').first.click() | ||
expect(page.get_by_role('img')).to_contain_text(re.compile(r'.+0.00.10.20.30.40.50.60.70.80.91.0')) | ||
expect(page.locator('.comparison-grid')).to_be_visible() | ||
|
||
# Test visibility of exercise histogram | ||
def test_histogram_visibility(page: Page) -> None: | ||
login(page) | ||
page.get_by_role('link', name=' Exercise histograms').click() | ||
expect(page.get_by_role('img').first).to_contain_text(re.compile(r'.+0.00.10.20.30.40.50.60.70.80.91.0')) | ||
|
||
# Test visibility of student view | ||
def test_student_view(page: Page) -> None: | ||
login(page) | ||
page.get_by_role('link', name=' Students view').click() | ||
page.locator('.sorting_1 > a').first.click() | ||
expect(page.locator('.content.container-fluid > p').first).to_contain_text( | ||
re.compile(r'All comparisons for .+ with similarity greater than .+%') | ||
) | ||
|
||
# Test visibility of flagged pairs | ||
def test_flagged_pairs(page: Page) -> None: | ||
login(page) | ||
page.locator('td > a').first.click() | ||
page.get_by_role('link', name=re.compile(r'.+% .+ vs .+')).first.click() | ||
page.locator('[name="review"]').click() | ||
page.get_by_role('link', name='Plagiate', exact=True).click() | ||
page.locator('.breadcrumb > li:nth-child(2)').click() | ||
page.get_by_role('link', name=' Flagged pairs').click() | ||
page.get_by_role('link', name=re.compile(r'.+ vs .+')).click() | ||
page.get_by_role('link', name='Get summary of marked').click() | ||
expect(page.get_by_role('heading')).to_contain_text('Similarity Summary') | ||
page.locator('.breadcrumb > li:nth-child(2)').click() | ||
page.locator('td > a').first.click() | ||
page.get_by_role('link', name=re.compile(r'.+% .+ vs .+')).first.click() | ||
page.locator('[name="review"]').click() | ||
page.get_by_role('link', name='Unspecified match', exact=True).click() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[pytest] | ||
# Run chromium without UI | ||
addopts = --output test_results --browser chromium --browser firefox | ||
python_files = test*.py | ||
testpaths = | ||
./e2e_tests | ||
|
||
DJANGO_SETTINGS_MODULE = radar.settings |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,4 +8,10 @@ git+https://github.com/apluslms/[email protected]#egg=django-essential | |
git+https://github.com/apluslms/[email protected]#egg=a_plus_client | ||
git+https://github.com/apluslms/[email protected] | ||
aplus-auth ~= 0.2.3 | ||
django-debug-toolbar | ||
setuptools ~= 68.1.2 | ||
django-debug-toolbar ~= 4.4.6 | ||
pytz ~= 2024.2 | ||
pylibmc ~= 1.6.3 | ||
pytest-playwright ~= 0.6.2 | ||
pytest-django ~= 4.9.0 | ||
pytest-env ~= 1.1.5 |