How to run the tests (moodle 45)

Versión 2 (Emilio Penna, Jueves, 19 de Marzo de 2026 10:07:52 -0300)

1 1
h2. JMeter script configuration
2 1
3 1
The script requires the JMeter Plugins Manager. Download @plugins-manager.jar@ from
4 1
https://jmeter-plugins.org/install/Install/ and place it in @lib/ext/@ (restart JMeter).
5 1
6 1
Tested with JMeter 5.6.3 and Moodle 4.5.
7 1
8 2 Emilio Penna
h3. User-defined variables (Test Plan level)
9 1
10 2 Emilio Penna
All parameters are configured as user-defined variables at the top of the Test Plan:
11 1
12 2 Emilio Penna
|_.Variable|_.Description|_.Example|
13 2 Emilio Penna
|@curso@|Course ID (numeric)|@2@|
14 2 Emilio Penna
|@prueba@|Quiz module ID (numeric, the @cmid@)|@2@|
15 2 Emilio Penna
|@host@|Server hostname (no protocol)|@eva-perf.seciu.edu.uy@|
16 2 Emilio Penna
|@servidor@|Server URL with protocol|@https://eva-perf.seciu.edu.uy@|
17 2 Emilio Penna
|@port@|HTTPS port|@443@|
18 2 Emilio Penna
|@csvfile@|Absolute path to the users CSV file|@/home/user/perftestusers5000.csv@|
19 2 Emilio Penna
|@twaitmin@|Minimum think time in milliseconds|@30000@|
20 2 Emilio Penna
|@twaitmax@|Maximum think time in milliseconds|@90000@|
21 2 Emilio Penna
|@assertiontext1@|Text asserted on quiz pages (English)|@page@|
22 2 Emilio Penna
|@assertiontext2@|Text asserted on quiz pages (Spanish)|@página@|
23 1
24 2 Emilio Penna
The @assertiontext1@/@assertiontext2@ pair handles Moodle installations in either language.
25 2 Emilio Penna
They verify that quiz attempt pages loaded correctly after each @processattempt.php@ call.
26 1
27 2 Emilio Penna
h3. Thread Group
28 1
29 2 Emilio Penna
Set the number of threads (VUs) and ramp-up time in the Thread Group. The script is configured
30 2 Emilio Penna
for a single iteration per thread (@LoopController.loops=1@): each virtual user logs in,
31 2 Emilio Penna
completes the quiz once, and exits. On error, the thread stops (@stopthread@).
32 1
33 2 Emilio Penna
We tested up to 3000 threads with a 180 s ramp-up.
34 1
35 2 Emilio Penna
Start with 1 thread to confirm the script runs without errors before scaling up.
36 1
37 2 Emilio Penna
h3. CSV Data Set Config
38 1
39 2 Emilio Penna
The script reads user credentials from the CSV file. Columns are: @user,n1,n2,mail,pwd@.
40 2 Emilio Penna
Set the @csvfile@ variable to the absolute path of your users file.
41 1
42 2 Emilio Penna
h3. Synchronizing Timer and Gaussian Random Timer
43 1
44 2 Emilio Penna
The script simulates students starting the exam at the same moment using two timers placed
45 2 Emilio Penna
inside the @startattempt@ transaction controller, just before the POST to @startattempt.php@:
46 1
47 2 Emilio Penna
* *Synchronizing Timer* (@groupSize=0@): holds all threads at this point until the entire
48 2 Emilio Penna
  thread group has arrived, then releases them simultaneously. This models the worst-case
49 2 Emilio Penna
  scenario of all students clicking "Start attempt" at exactly the same time.
50 2 Emilio Penna
* *Gaussian Random Timer* (deviation @30000@ ms, offset @5000@ ms): after release, each
51 2 Emilio Penna
  thread waits a random delay before actually sending the startattempt request. With these
52 2 Emilio Penna
  settings, approximately *66% of threads fire within the first 30 seconds*, and ~95% within
53 2 Emilio Penna
  the first minute. This models the real-world observation that in large exams, 55–75% of
54 2 Emilio Penna
  students tend to start in the first minute, making this a conservative worst-case scenario.
55 1
56 2 Emilio Penna
h3. Think time
57 1
58 2 Emilio Penna
Each quiz page uses a @TestAction@ pause of @${twait}@ milliseconds, where @twait@ is
59 2 Emilio Penna
initialized per thread at the start of the test by a JSR223 sampler (Groovy) that picks a
60 2 Emilio Penna
random value uniformly between @twaitmin@ and @twaitmax@. This means each virtual user has
61 2 Emilio Penna
a *fixed* think time for the entire test, but different users have different values — a
62 2 Emilio Penna
reasonable model for students answering at different speeds.
63 1
64 2 Emilio Penna
h3. Script coverage and limitations
65 2 Emilio Penna
66 2 Emilio Penna
The script covers the main HTTP interactions of the quiz flow: login, course page, quiz view,
67 2 Emilio Penna
exam start, answering all 16 questions across 8 pages (via @processattempt.php@), and
68 2 Emilio Penna
finishing the attempt. Quiz attempts and answers are saved correctly in Moodle — this has
69 2 Emilio Penna
been verified after each test run by reviewing the quiz results in the admin interface.
70 2 Emilio Penna
71 2 Emilio Penna
The script does not replicate every browser request. In particular, it omits most AJAX calls
72 2 Emilio Penna
(e.g. autosave, flag updates, analytics beacons) and does not fetch all embedded static
73 2 Emilio Penna
resources on each page. A real browser session generates significantly more requests per page.
74 2 Emilio Penna
However, the requests that drive server-side PHP processing — which is the actual bottleneck —
75 2 Emilio Penna
are all included. The "get static resources" controller in the script is disabled; static
76 2 Emilio Penna
asset delivery is better tested via @mod_cache@ or a dedicated CDN rather than through JMeter.
77 2 Emilio Penna
78 2 Emilio Penna
The @sesskey@ token (Moodle's CSRF protection) is extracted dynamically via regex after login
79 2 Emilio Penna
and after the quiz view page, and included in all subsequent POST requests. The @attempt@ ID
80 2 Emilio Penna
is similarly extracted after @startattempt.php@ and used throughout.