From 88e68f5342736ff3932e59fcd5a9b5b783ac45c5 Mon Sep 17 00:00:00 2001 From: Mateo Date: Mon, 3 Nov 2025 20:07:09 -0500 Subject: [PATCH 1/2] Add autotest guide --- Developer-Guide--Autotester-Technical-Tour.md | 34 ++++++++++++++++++ images/AutoTest_diagram.png | Bin 0 -> 52848 bytes 2 files changed, 34 insertions(+) create mode 100644 Developer-Guide--Autotester-Technical-Tour.md create mode 100644 images/AutoTest_diagram.png diff --git a/Developer-Guide--Autotester-Technical-Tour.md b/Developer-Guide--Autotester-Technical-Tour.md new file mode 100644 index 0000000..0596355 --- /dev/null +++ b/Developer-Guide--Autotester-Technical-Tour.md @@ -0,0 +1,34 @@ +# Developer Guide: A technical tour through the autotester. + +The autotester is a program designed to automatically run student assignments against preconfigured test files. + +## Python Autotester + +![Autotest Diagram](images/autotest_diagram.png) + +The autotester has three major components: +1. Client - Flask API Client +2. Server - Python Server +3. Cache - Redis Cache + +The python autotester has two testers to choose from: +1. Pytest - Third party PyPy project +2. Unittest - Builtin testing framework + + +### Test Creation + +1. Markus + i. The `update_test_specs` [function](https://github.com/MarkUsProject/Markus/blob/master/app/controllers/api/assignments_controller.rb#L199) updates several local records with the information provided. + ii. The `AutotestSpecsJob` which calls the `automated_tests_helper.update_settings` function + iii. The `update_settings` obtains all the settings information and makes a call to the Autotester Client api, to either update the settings or create a new settings record +2. Autotest Client + i. The autotest client on a new test creation, will have it's `/settings` [endpoint](https://github.com/MarkUsProject/markus-autotesting/blob/master/client/autotest_client/__init__.py#L213) called which does 2 things. 1. Incremement the `autotest:settings_id` and 2. save the settings provided from MarkUs onto the redis cache as `autotest:settings` + +### Test Execution + +1. Markus + i. When a test is scheduled, a resque + + + diff --git a/images/AutoTest_diagram.png b/images/AutoTest_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..86de42b22696b522ea1e84bb27e4b2de6b2a4565 GIT binary patch literal 52848 zcmc$`byU<}*EUYa&@prfN)3_*-2&1B3|-O!(%lV$5)y(^LkUQ#Al)E>bO-`UgLHSj zXTJCS{O;#n@3YqLpLea7Kjx2_PwcbLIs07u+SeuquC7P~p@X2Ip%E!PeWHbih6zPO z!%)D(0pIYr6tAJ7-9b}&B7^WT-O9oZq3AyCnL8e2^gd#j=gRYtA*IB^N@bNNgLcJE z%?wop`{Vj|hlQDt$zW4rVWZn=#sBed4Bx!wz4c9=d61^E^El(h=f?B+sCyYDbG5w# zwsRT35|@{)=vidYIiJ~Ke;ClHJv!qT&chGax`Rm>f&oW^NQZ`Skzy3%rJp>fft;zK zN5#%1oRy0_T(-r=d5ncPGjMx|i;YAB7pp_iU@pqip?BbDaC67In6NTOv)9BBY4B(q zY&57%75N1ob`t^(zEBu~!$(}qUl%$o!HI^AlqTgwE5^gPYxxp&=e9fQ_Dc&7)XUKy zfS>roQ->8f=L<1HAbi*leO#p@+leA}fXQgsVbbW*@}xAhauMK1ha61sF+-gnjxs!5 z23aN{NQhzhnR(Gc7cXs6n?8 zf}i@Iu^o{?d`i%e9V+NVrVMa%7tCD$e;jfLerI_}WOqJ(no8*CwjywL@ov|iy%ri= zGg)@^23+ZMnS1(=_1v6ya#7&0XU)S3tUq=GV(Qkan)A= z0a26>LzKW6)5l%x8;OeHr71Os=qUI5{2z0WL>-8Q@L|c0jKzT6w^Bu2p!)Ag(gKsj z{wQd^<bI)gScRTfeR(zh#9e*#Z|zsj=RQ`E2QyTvg%b~$^4y($k`0gR z4Qu4%ov$-~4g_TL`YorytXt9(Wz!@ZBa+@{8tngym(Lm9X>HAwNf^-n9rZ>K1NPdA z=m`6tWts`r;(aG?>Bw%PGB+Qakl4jAh7I2(qw%^Wd1(H{b+>tn?{j+3mPLGN`A1)I z5XD!lcj*7Mb^m@qL&^%-#c2v4J7~P{Jox(2pvTik1&N8I3#mRTeL9J$3hp^uib`=a znqPK0*$`IDGitX%mz0IuhVnHTp2#oJw+S278_EWXUc=vVObbPeyz{S1*Wf)rn9BAL zDU>T?pGnxYzPLwe9=a=Pt7XR~g&7;3c7E}AHZVjd zxV{`nerVCBK;D(F<#=mL;8pzmcf+HBY>ABNua2AA`+QA%vUCq@2-Px$N35HNBrorq zc>nhN{CjI_%YG(4F0PQfvMEXOe3_#5e03;?Z_^?%CO-bd?5y#-(=S7k`5f6kvd2^3 z5|}l<*bL;Am6a)54~ieE`t5g9bBTz&+xS_olJVFv≀r`eb`%?W@zzufB(?M>Ec? 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 literal 0 HcmV?d00001 From 97a983938d2ea6351bc58dcb22e98a9029cbcc88 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 01:07:56 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- Developer-Guide--Autotester-Technical-Tour.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Developer-Guide--Autotester-Technical-Tour.md b/Developer-Guide--Autotester-Technical-Tour.md index 0596355..b0ef67c 100644 --- a/Developer-Guide--Autotester-Technical-Tour.md +++ b/Developer-Guide--Autotester-Technical-Tour.md @@ -1,4 +1,4 @@ -# Developer Guide: A technical tour through the autotester. +# Developer Guide: A technical tour through the autotester The autotester is a program designed to automatically run student assignments against preconfigured test files. @@ -7,15 +7,16 @@ The autotester is a program designed to automatically run student assignments ag ![Autotest Diagram](images/autotest_diagram.png) The autotester has three major components: + 1. Client - Flask API Client 2. Server - Python Server 3. Cache - Redis Cache The python autotester has two testers to choose from: + 1. Pytest - Third party PyPy project 2. Unittest - Builtin testing framework - ### Test Creation 1. Markus @@ -29,6 +30,3 @@ The python autotester has two testers to choose from: 1. Markus i. When a test is scheduled, a resque - - -