From b0b68b06d30a7d30008e8e7037fad1d67e7d0798 Mon Sep 17 00:00:00 2001 From: MrWaradana Date: Mon, 23 Feb 2026 14:51:27 +0700 Subject: [PATCH] unit test --- Jenkinsfile | 12 ++ src/__pycache__/__init__.cpython-311.pyc | Bin 143 -> 139 bytes src/__pycache__/api.cpython-311.pyc | Bin 5606 -> 5602 bytes src/__pycache__/config.cpython-311.pyc | Bin 4836 -> 4832 bytes src/__pycache__/enums.cpython-311.pyc | Bin 1065 -> 1061 bytes src/__pycache__/exceptions.cpython-311.pyc | Bin 7437 -> 8455 bytes src/__pycache__/logging.cpython-311.pyc | Bin 4872 -> 4987 bytes src/__pycache__/main.cpython-311.pyc | Bin 5506 -> 5990 bytes src/__pycache__/models.cpython-311.pyc | Bin 7224 -> 7220 bytes src/__pycache__/rate_limiter.cpython-311.pyc | Bin 335 -> 331 bytes src/auth/__pycache__/__init__.cpython-311.pyc | Bin 148 -> 144 bytes src/auth/__pycache__/model.cpython-311.pyc | Bin 535 -> 531 bytes src/auth/__pycache__/service.cpython-311.pyc | Bin 3809 -> 3805 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 152 -> 148 bytes src/database/__pycache__/core.cpython-311.pyc | Bin 8688 -> 8684 bytes .../__pycache__/service.cpython-311.pyc | Bin 6538 -> 6534 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 153 -> 149 bytes .../__pycache__/model.cpython-311.pyc | Bin 10376 -> 10372 bytes .../__pycache__/router.cpython-311.pyc | Bin 16624 -> 16620 bytes .../__pycache__/schema.cpython-311.pyc | Bin 16483 -> 16479 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 160 -> 156 bytes .../__pycache__/model.cpython-311.pyc | Bin 2597 -> 2593 bytes .../__pycache__/router.cpython-311.pyc | Bin 2436 -> 2432 bytes .../__pycache__/schema.cpython-311.pyc | Bin 3755 -> 3751 bytes .../__pycache__/service.cpython-311.pyc | Bin 2918 -> 2914 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 154 -> 150 bytes .../__pycache__/model.cpython-311.pyc | Bin 1086 -> 1082 bytes .../__pycache__/router.cpython-311.pyc | Bin 6440 -> 6436 bytes .../__pycache__/schema.cpython-311.pyc | Bin 4220 -> 4216 bytes .../__pycache__/service.cpython-311.pyc | Bin 14452 -> 14448 bytes .../__pycache__/config.cpython-311.pyc | Bin 2416 -> 2412 bytes .../equipment/__pycache__/Eac.cpython-311.pyc | Bin 15665 -> 15661 bytes .../__pycache__/Prediksi.cpython-311.pyc | Bin 52571 -> 52567 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 160 -> 156 bytes .../__pycache__/model.cpython-311.pyc | Bin 2635 -> 2631 bytes .../__pycache__/router.cpython-311.pyc | Bin 4715 -> 4711 bytes .../__pycache__/schema.cpython-311.pyc | Bin 7964 -> 7960 bytes .../__pycache__/service.cpython-311.pyc | Bin 3703 -> 3699 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 166 -> 162 bytes .../__pycache__/model.cpython-311.pyc | Bin 5383 -> 5379 bytes .../__pycache__/router.cpython-311.pyc | Bin 8338 -> 8334 bytes .../__pycache__/schema.cpython-311.pyc | Bin 11852 -> 11848 bytes .../__pycache__/service.cpython-311.pyc | Bin 14712 -> 14708 bytes .../__pycache__/__init__.cpython-311.pyc | Bin 152 -> 148 bytes .../__pycache__/model.cpython-311.pyc | Bin 1764 -> 1760 bytes .../__pycache__/router.cpython-311.pyc | Bin 4627 -> 4623 bytes .../__pycache__/schema.cpython-311.pyc | Bin 4368 -> 4364 bytes .../__pycache__/service.cpython-311.pyc | Bin 3883 -> 3879 bytes test_masterdata_output.txt | 111 +++++++++++++ test_masterdata_output_2.txt | 155 ++++++++++++++++++ test_output.txt | 38 +++++ test_output_e2e.txt | 141 ++++++++++++++++ tests/conftest.py | 90 ++++++---- tests/database.py | 3 - tests/e2e/test_acquisition_cost.py | 23 +++ tests/e2e/test_equipment.py | 26 +++ tests/e2e/test_equipment_master.py | 8 + tests/e2e/test_healthcheck.py | 8 + tests/e2e/test_masterdata.py | 97 +++++++++++ tests/e2e/test_masterdata_simulations.py | 8 + tests/e2e/test_plant_fs_transaction.py | 16 ++ tests/e2e/test_plant_masterdata.py | 20 +++ tests/e2e/test_plant_transaction.py | 18 ++ tests/e2e/test_simulation.py | 19 +++ tests/e2e/test_yeardata.py | 18 ++ tests/factories.py | 33 ---- tests/unit/test_masterdata_logic.py | 24 +++ tests/unit/test_masterdata_service.py | 37 +++++ 68 files changed, 837 insertions(+), 68 deletions(-) create mode 100644 test_masterdata_output.txt create mode 100644 test_masterdata_output_2.txt create mode 100644 test_output.txt create mode 100644 test_output_e2e.txt delete mode 100644 tests/database.py create mode 100644 tests/e2e/test_acquisition_cost.py create mode 100644 tests/e2e/test_equipment.py create mode 100644 tests/e2e/test_equipment_master.py create mode 100644 tests/e2e/test_healthcheck.py create mode 100644 tests/e2e/test_masterdata.py create mode 100644 tests/e2e/test_masterdata_simulations.py create mode 100644 tests/e2e/test_plant_fs_transaction.py create mode 100644 tests/e2e/test_plant_masterdata.py create mode 100644 tests/e2e/test_plant_transaction.py create mode 100644 tests/e2e/test_simulation.py create mode 100644 tests/e2e/test_yeardata.py delete mode 100644 tests/factories.py create mode 100644 tests/unit/test_masterdata_logic.py create mode 100644 tests/unit/test_masterdata_service.py diff --git a/Jenkinsfile b/Jenkinsfile index 55d7922..f9a3e7e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -43,6 +43,18 @@ pipeline { } } + stage('Run Unit Tests') { + steps { + sh 'poetry run pytest tests/unit' + } + } + + // stage('Run E2E Tests') { + // steps { + // sh 'poetry run pytest tests/e2e' + // } + // } + stage('Docker Login') { steps { // Fixed variable names based on the 'DOCKER_AUTH' environment key diff --git a/src/__pycache__/__init__.cpython-311.pyc b/src/__pycache__/__init__.cpython-311.pyc index 426c2483b7abe0c04ad706bbaffb96541c02573f..a55b27f4dbeabf2de4a24ecd56e5fd495264d78f 100644 GIT binary patch delta 44 ycmeBY>}KRy&dbZi00j2C)@4lOF%gk-wu(tfEsIG?)y+vxPK+roN{*QrVGaNR#0?<; delta 48 zcmeBX>}TXz&dbZi00akfc`_&Rm`Et;XXNLm>L+IA=IbY=>gFUTC+Zg$CF@TNF$VxD Chz-X8 diff --git a/src/__pycache__/api.cpython-311.pyc b/src/__pycache__/api.cpython-311.pyc index dc55969c6178fe27322c40735f0f575b97b6f50a..7e81a85ee4cf0c43e16c93ad03996bc91e175123 100644 GIT binary patch delta 49 zcmaE+{YaZ{IWI340}x0?cxSo@Y~ diff --git a/src/__pycache__/config.cpython-311.pyc b/src/__pycache__/config.cpython-311.pyc index 95f6f552f3e4b6dac98333382238072dd72464b6..825efb63fb99b45f35909f72fea6908f1af1d2ed 100644 GIT binary patch delta 49 zcmaE&`aqR$IWI340}$-|(4EQ6yOHlOi-?S~RZL21Sxi!@ZccJ?VoY&Sa?IwJEWddH Dg?bS7 delta 53 zcmaE$`b3p)IWI340}z-WZOdHFvytyGi-dxHMt*Lpeqv^BzJ5}wZccJ?qJD8vvi|0$ HEWddH!2S{O diff --git a/src/__pycache__/enums.cpython-311.pyc b/src/__pycache__/enums.cpython-311.pyc index 1c7f55dffce2941e40ae018e187ca20210650e2f..8d88bbfe917939fd7341d0902b3cba778417b212 100644 GIT binary patch delta 48 zcmZ3%IWI340}$BnT9;wBkvEu0MB3RZCMC5jCMi`nCpkGWrno3MW^)D8Mn(WZ CwGN;F delta 52 zcmZ3=v66##IWI340}vd{<;hgv$Q#TgA+Mj2pPQ7%Q6rS~Zy&M1U#{bTb^QY88F(^a=J5fM|P;rTbtVW`^jf~gCwl=XDFI5_C zY7P}h&`Jq|_-O<60YU&*1cd_J~jAU7g#Dyzt)U-&wz?(ShI4Hn@k>{IvGjHB} z{@&ZUm3aHS^9zT=ilDvz?yda&;J3~ztS9nZA|+?9re4jCDVa<P>_?z(}D7{2GxCaiyL>>=5@VXoQ8vr<13AO~GRG9m^Zw`)wnVYtAJ z4zQgac8h@p7&wm^^oQI2GJl$U!AX7-edA|yQ~Qmu2%T}vFS<4vpbNd#s&1-;u)uWi z9;Ce4>*@&6q&VwVUF3VI*L9+jc+9bP(k$~D``<(~wsz*V6UMchCg23U)smoYq1&(u z?Hqt`5|GiP5UF){RlJ7BDyMNcu5qgt%~J3gtJv9To!;A~dw#>S5NOYW#%z@bk5JnZ zG!|~})_6dVCP2AxWWp2ldXLsmr12RAG$s50pEjX?(k2=p4?WXjXfCbf<+PeFE=95! z7crUjMl05RKagn`0sKu`+*I=WKLUJ+7LbN6Us+|;4j&m+ zJ1lTJZYpQYkc3oA+kh;}Opv4{KmE{RV42$T(mnRXs+l)gr~v4#RyEVAtgM@E&L>fn zd&I<=tWwN0*~Rig)2v=AWuq*n`NK4Im~bbsDN%J}Q*d)yDNn=1 za4W;HauMK7q$55ob$}fOdmh-3H`3@ExSPA3`@DSb$!&If<~!@&=wy9#a<6Zy-Z#~V z3{_`7vo?AoRo})dI&b#+4iLa0g+B!3A9$~@?or-Xbla)$c!0d)9VZjsVMo)PQ`J(G zIg)_<;9Yn*jGqQd_!$cHxx@5{!Sv&Zd z4-mj11)ahJ0l9k`f$%SZof)1w(r~iVWRdxxMnSwxQ_`(CmQbb2rq&dbZi00eT9&6$Q`8~NgxB~g5M6yb6D1JO@1LD&nP!}J(mPaQC*4R}|V74w}0y+tZAs`s!M?n}bO9;jSh8!=@8LLE;>xE%rwX8L) zMV2+JwQMzPSt2meB0gjus@w*U96UU;;EvA{hv}|m2da>O^Ehglfj0Biumef{8V+Dg zu`<;%Pqq^h7Zm_YA;Lru940-2verT=>^00KaKjlGutyQDkdeX_GMd7Z`NZrdUyx9l zoGvCW%#u-3QlQCri#4^Pq$tr(ld(u*@;nKn$xM=IVUk4_KtB}Og9v^Q!3QEh>8{8L zL|B3dFCcM?EhV)iF*B!#8zdqJB6vZB28aN8;TBhJeoAUid`f9n>eoR^o20SI=r_Gab^ZsfCL5|MSbib+W=i%Ck=%}Gv9j43Wkj@g{Tw3L(a z$!0E|WG1;<_H>3C_IR*9klqv)AWsOy0)feld}2%~tdryU{CU~@G?{O)mzHHF=NIKo zKFud3zz5~%B_=1Q78kose!_Q{kz?`-epmZjyb!VYoc#3k)S_YzpkWG7P$UlI+!9RA z&r8cpFD*(1tI5nuFDe6y#{hA$|700~tBm%OKMNQth{{|MQN5sMc2UIqiimlG?+sb` t2Hz_zQa9w3LA3N_MZwjKWs}be$}-kWel7S%QIpY+@dE>PvPcYQJOFI0RhR$( delta 217 zcmeyZ)}h9?oR^o20SIQD?#k2_*vMzcB%!FEk)NBYpO~4Oub-5vo0FWJs9#)^tiL&d zX(=b;g3W9^$xM^i@;S<~_-V4-VlOSrOwKRLtKx$)^b(VkQ;Uly|K^jLtj2$ck$v(@ zepmfscAzB+5KtrzWZx1@&d*EBOfM};jnBzXPtVLtFDeC!#{hA$?&Ms7t4x86lbr<( iCr=k#!B{%kK}eRddUBl5A4L^LKgJIX*vTR>pmqR2wm%;L diff --git a/src/__pycache__/main.cpython-311.pyc b/src/__pycache__/main.cpython-311.pyc index e7365addd0b79f7d3356f3c5df8b69dc7f303aa5..a58a2ef150129a984cfcfacae53b86d449837f72 100644 GIT binary patch delta 1911 zcmaJ?O>7fK6rQo;#IYUQaef>-BzEHbunBRXh@Y5*;247w(gcdiVVlZqypwd(UE9pA z3xQUVs-9>oKyxTUJk zQMYS?C|G=}I;0JY!`cpUhc+UPSXi4H*G9!ri^nP!F`LD`YnB*N_iFpZeHI^9_iJO~ zn3fO|+5z!^g>|aq+Jrb^@!Qmc+N3y%kqr^Na)=ko7fG&Tgl@vAE^!L2}X2n^n8p|h$ z$mG`MSi0A%@#OxkI(dM^mTdCiM|E49C(gm`UhT8}e?IfzbNp$)_HE4rkBLtrL14%2 z^TGBv$e9w+jZ>1U$daKH@@Yy7lznbr^7~Gnm`$p=cZjxXfw%v)pSIa{*4>usui?J; z>sNfW2axODwVsg1jQSde&~-mAz>Z`Gi#U65FS}D8!<_Gr^ln=9A$s(KhL`%)vsI^H zZ!j>s;0&`n&LOtec$r;jyff^aJ0F}8kzdM+; zr3L#v!2!a(xE&Pt6G>O5jy-AmwqqC6MpK+*c$Ib_(P)&;u^IH@&9r!H3T1=rkQS#cIuWhrkcIqKnJgRU0Nf;Da8lJ}_;xB9D7F9%)v z8C9xI7v+NlR?h&Qg!*3u3sj@c9BhByl0Ejhae)2fi`2J(lD4uQe@Cc|+ciVQR3(N% z;4_n&nrb57w|IHB&^0BV|G+fU`;$uwtI8?k!KBtyslI7hb^lL=txo!r?-_CKZAeU5fkd{E? z{|5R`EEG8B-(#XJn_UVl_=iliW#9fYa33c_4^Zgph$)P1phOuZOq6(t?7tumo8g`2 zYf~F2RYoZjrJmteN6p~_8)&?Y#!WQNzG+>Ib>h|=!N&+bo8&J$vUQYk@Ue}<2ia)b Id>ya-KUpR9t^fc4 delta 1487 zcmaJ>O>7%Q6rS0&6R#6HUfaY@Qpa}PG;u<`ia^beo1~`saUe~EC_-9MqV4V^*=X16 z%&yghOC`hsdVy#TNF1tgNs(FvQtog_;XpYQDdJ#>8-h!b!i7T*6>se34heAOF?VHDU%^Q*Ja1vkG?*BSrr_>Zi1~S4{ubo!Yjdh2${bxRB z52yonUd=b4m^Ek*sY8u5wy=u9C2p}{+{u=3`i^~By=;%DBMrXG8nwsNvBtXF8n=sT z5hDQ+yncnBfHyL+ixGMNquJC+;FVoa9vndkBQizCOsrl7E=aB#J;pgBW%NEw@A|#rRF%fm-2Qrfx3vO=s2kvNI&3g8B#*&uvrXPUDLA~_@TF#B&FQao?X z*t6=aJ*UpuWwm_blR%_+HiZT^-;8JE&T_^Dl3o#vz7Kt8Q&eAvGyK2L#sB!c0X_>a zvU=t0K5*suEtKzPPsJtnwol)C?7JxlzleK-t)F9-k#g9_o(Ho28#&}<*t(R$G7lso z!_V$Xd9lUAY)9&5ze$5wVqXNe*}dR*7h4zKkIq+g$2Kdg8A>*4#P!BA&u}J>>yoQG zRkBj6=cNtiB*kBWX!zDFVuKZHubxdfZ;_-aIf{b-4c zS-vyRGn2{CGR*b3W*EyZ(QDN7wwBk3W)SMq1)$zx1CcVm&Nd>8cjOffE~07{C~>P! z#U(D~Uu!*3-7>U_XX><#tF5l(+y*n+&b9Cht>rWAghsht6i!7g;&}v4)_8cA#yBCLBAl8Bl|kd+ zpT;k-r*f*VliS2j*&L^p;IWfjbg@FTr`*jgC3wC9snl$j_Hez8>rh3jJnlJ;L^wjB zRF*B%Ha*BV#o<;C^9$)^+tI{(X~3GrmE~->5%#E_TzdW(v`xdX$Zd@hn&Y6fO1uTw z58_Vo7_V}{|5mh*)1p?b(oxnD8_n_xr@S1S^&31DiI*N-V9T-2-s^nH-~UwA3+ diff --git a/src/__pycache__/models.cpython-311.pyc b/src/__pycache__/models.cpython-311.pyc index 09d2e86c8473e01d49e824724c65fd96840a2e82..e07e086c134dd78ea5fb97f72972013a30735686 100644 GIT binary patch delta 48 zcmdmCvBiRSIWI340}$-|(4F~vBdWvUOiF55Oj4?DPI7W$OmR_i%;pl7BjNyp C;t-Dj delta 52 zcmdmDvBQFQIWI340}xmTRb)1Af-(0|Q GL>vHzQxEz8 diff --git a/src/__pycache__/rate_limiter.cpython-311.pyc b/src/__pycache__/rate_limiter.cpython-311.pyc index 75029b1f710337947d585bfe414201a482ed9190..d9d7738dd1592f0b3b03859790c8a44035846eee 100644 GIT binary patch delta 45 zcmX@lbef5GIWI340}$BnT9;8bk#~=XlCxDzN@`h5QmSrFa&lr!aZz&2#D{qRITa6Y delta 49 zcmX@jbe@TKIWI340}vd{<;kp^$h${EO+O<)H&s6|GdEv9DOEQoIXO|kxF}hF;@vy| DX9W-t diff --git a/src/auth/__pycache__/__init__.cpython-311.pyc b/src/auth/__pycache__/__init__.cpython-311.pyc index e42b5d501a8fb9db5018a502a71ae35baf18f743..224f452c1b83dc15720bd262e530484613ff9cf6 100644 GIT binary patch delta 49 zcmbQjIDwI8IWI340}$BnT9+}A$3#-u*(xR_wJatnRW~O&IWeZVC^;svv?L>DVyrm; DO*;=r delta 53 zcmbQhIE9gCIWI340}vd{<;k4LVk(ZZIQo-3OCMC5jCMi`nCpkGWrno3MCb6_6BWAKW G;{yP9D-cHj delta 56 zcmbQtGM$BYIWI340}vd{<;l$6$ji$ptD>KgpPQnEk^<|HR4>K7L!>!&1^ QBqk*mr|NHZWpxw*03I0hX4Qo delta 58 zcmbQrIFpfQIWI340}vd{<;k4LW1^&^pOK%Ns-Kvdo3Edgs+*IXoTy)1l&qgxSejXo Mo0?amKQYc60MqFb00000 diff --git a/src/equipment/__pycache__/model.cpython-311.pyc b/src/equipment/__pycache__/model.cpython-311.pyc index b10150a5e8961e44f74b454b614e814b45458810..468b9f5ced71b0dad5404a3f46e006a91e93f4d8 100644 GIT binary patch delta 59 zcmeAOYzgFB&dbZi00cWfbZ0iGY~-_KlT&rJib+W=i%Ck=%}Gv9j43Wkj!7*n%`C`G N%`1u7oXIAy1OP0H6Py45 delta 63 zcmZn(>nEk^<|HR4>K7L!>!%i$ RW)|e8=9TDgPGyr<0suSi6IB2J diff --git a/src/equipment/__pycache__/router.cpython-311.pyc b/src/equipment/__pycache__/router.cpython-311.pyc index 77bb12825b6452736035b199f7a1ac7a42e55c82..2b8e1a6a13064e710a837d06ed752cad4213bbce 100644 GIT binary patch delta 61 zcmey+$oQs_k#9LKFBbz4m~!`I9yQv?w~uhT>NGL- diff --git a/src/equipment_master/__pycache__/model.cpython-311.pyc b/src/equipment_master/__pycache__/model.cpython-311.pyc index abfe1c6d3d3737415b894065f1a0b49516343d25..ae571cccbaea35e02ae9eaec87299b1ad8837478 100644 GIT binary patch delta 66 zcmZ1~vQUI?IWI340}$BnT9?7kv5_x{RaM8?DkdehEG8*cHzzqcF{ZdEIVQERG_xQ# UHLoN-H?g=RwJ2uuOx7M20Et5t-~a#s delta 70 zcmZ1|vQ&g`IWI340}x!|iOW30zL779RntH}BR@A)KQS{mUq2~THzzqcQNOq-SwFR~ YG_xQ#HLoN-H?g=RwMc*SRMs9A0OsQt7XSbN diff --git a/src/equipment_master/__pycache__/router.cpython-311.pyc b/src/equipment_master/__pycache__/router.cpython-311.pyc index 7ddee05d29c5b4f08a2cbdfe481fe39abe346a59..fad7adaf6844502c7411512e23feaf59529b4fb3 100644 GIT binary patch delta 65 zcmZn>ZV={O&dbZi00h^3D>D5y@_uJl)pfRtNl7h>NlMktNls3TDK1KmNi8hREXYmG TD~ZodEG|hcirK8o63z+$ltmS} delta 69 zcmZn=ZV~2P&dbZi00ePv6`67ydA~Dj8tP}{=cei>X6EMWC#CA2KC#311NZU6uP delta 70 zcmZ23yIPiSIWI340}#ZyRb<{_-N+ZttZAs9k)NBYpO~4Oub-5vo0FWJs9#)^te;v~ Ynpu#WnpYB^n^;_uTBN_Zi&>T%0Oso!q5uE@ diff --git a/src/equipment_master/__pycache__/service.cpython-311.pyc b/src/equipment_master/__pycache__/service.cpython-311.pyc index a923155c29bd3079316aae24bc38619ec7dd087d..6d7dc6c6a8b4af66bb17325233b65c0ff0606d0e 100644 GIT binary patch delta 65 zcmaDR_DGC(IWI340}$BnT9=Wxk=L6^RnOTfCMC5jCMi`nCpkGWrno3MCbh6MvmiG$ TuOvPo&G diff --git a/src/masterdata/__pycache__/model.cpython-311.pyc b/src/masterdata/__pycache__/model.cpython-311.pyc index 892b12a129b5f9502e020012a0ebbb13e4536700..ae67aeb30de10edd73fa669148af84c76dc16daf 100644 GIT binary patch delta 59 zcmdnTv5SLuIWI340}x0?cxSHK$m_=>ujXtOlag8%la#8PlboCwQ(TlBlbcvvl3J9K NSdtjCxsK@oBLMXJ67&E7 delta 63 zcmdnRv5$jyIWI340}w=gGtZo{k=Kt&SxY}7KQ~oBF*7$`KPgo=CpkG$zqlw_KR2 delta 64 zcmZ2tw8DsQIWI340}vc-?98ke+{nkvrmU@>k)NBYpO~4Oub-5vo0FWJs9#)^te=}$ ST#{Opl30?czuAiIl@I`Kz7)Rz diff --git a/src/masterdata/__pycache__/schema.cpython-311.pyc b/src/masterdata/__pycache__/schema.cpython-311.pyc index 1531dca8e1731ef53d13b2fa164043c90ec175f2..1ebe3df49bd98813b37dd5b66cf18d4357e73a21 100644 GIT binary patch delta 59 zcmeyP@I!%jIWI340}x#Et;jsRk@p>oyt=bhOiF55Oj4?DPI7W$OmR_iOm1RvNor9_ NVo74mW;xb4ZUA4M6pjD@ delta 63 zcmeyN@JE4nIWI340}#ZyRb+N=nCMy6x_Y*<@ diff --git a/src/modules/equipment/__pycache__/Eac.cpython-311.pyc b/src/modules/equipment/__pycache__/Eac.cpython-311.pyc index 337131275f9427471eee3f353aa109abb7b1b23b..6b8e5e2095b13574c9cf05763081b2c34c8d508e 100644 GIT binary patch delta 67 zcmdm3wYG|HIWI340}$-|(4G0fWh0+IlbW`(RZL21Sxi!@ZccJ?VoY&Sa!hW1N@-4N VaZGAqX=XugYFta$JOWIWI340}$BnT9V delta 69 zcmX>ua$1CUIWI340}vd{<;mQ!kvEr3(?CBXKQ~oBF*7$`KPgo=CpkG$zqlw_zaS?u XuOvP?IWI340}$-|(4ASZkvEA|RoB@nCMC5jCMi`nCpkGWrno3MrXVLVuOvP< TvA86)C?&BZF=q1&*2_Eq+%OlR delta 69 zcmaE^@>+#=IWI340}!}`c4qQyfFUU#E XD~ZodEG|hcN=Yn9)ZaXX^)e3t-`N)s diff --git a/src/plant_masterdata/__pycache__/schema.cpython-311.pyc b/src/plant_masterdata/__pycache__/schema.cpython-311.pyc index 511e8aaa4c13f3ca9db9ba6a66740e6e61090784..49fa0130b7955d7d0c1cf97d604790d4a78e5e7a 100644 GIT binary patch delta 65 zcmbPZH^Yv1IWI340}z-VT$gcaBX0n=s;;wDOiF55Oj4?DPI7W$OmR_iOhHa!UP*jz TVsS}oQA%P-V$9|??rFjRvxyeE delta 69 zcmbPXH^+{5IWI340}vd{<;kqx$Q!_|X{eu(pPQ5%^fpZt+m Mj8T6x2j6ct0Op?&wg3PC diff --git a/src/plant_transaction_data/__pycache__/router.cpython-311.pyc b/src/plant_transaction_data/__pycache__/router.cpython-311.pyc index a2ae08184d22148d4a8bd6d734744c05a38ba3a4..08b112e53cf6181e0dd9ea53754b5c86cccdfcff 100644 GIT binary patch delta 72 zcmbQ_*yqT%oR^o20SI<}=+0a(xsflHUEA2%DkdehEG8*cHzzqcF{ZdEIi?^dF|Q=P aq$n}3I5D{-Ge0jrC9xziX7eoe9})m;l^Qw# delta 59 zcmeBkoaD&2oR^o20SH_|J2US}Y~+h&moV4Q$j?pHPt45C*H22-%}Gv9)Gsbd)}LI@ NF2<<8c^dl<2>|}55;gz; diff --git a/src/plant_transaction_data/__pycache__/schema.cpython-311.pyc b/src/plant_transaction_data/__pycache__/schema.cpython-311.pyc index aaf073cbb71248845dacf9dd789df3260367eca0..b3bdb63b8c6ec42ca7374d0c560f2f66c418dffa 100644 GIT binary patch delta 54 zcmX>Tb0UU!IWI340}$-|(4BdABkyVn5o2eon3UAAn50zQoaE%hnBt=3n8_C;#28~X JKbJ@q1ppDg6MO&w delta 75 zcmX>Rb0&s&IWI340}#C0)R>vJk$1I(zPWxzer~FMVrFi>ep0G#PI7XhesNK@ diff --git a/src/yeardata/__pycache__/model.cpython-311.pyc b/src/yeardata/__pycache__/model.cpython-311.pyc index b5483a110d12bbe8632066399357cbf8aee91b2d..b53a3aa069e188e8ad58cc4989b54d18d3328f4d 100644 GIT binary patch delta 57 zcmaFD`+%2sIWI340}x0?cxMJ}NlMktNls3TDK1KmsZ32QN=Yn9 LjM<#QQo{rQ&*u@U delta 61 zcmaFB`-GQwIWI340}wc~xn|mIk!&rQ`&%*@T#PfFFzNls4GFD^>fuS`uW PN=Yn9)Zd)KQo{rQ238VF diff --git a/src/yeardata/__pycache__/router.cpython-311.pyc b/src/yeardata/__pycache__/router.cpython-311.pyc index 07b7983ecfe9fbd8b44398bb1126004ff20df722..e17ef971fef8ed51f7540dd8197989c170ec7f90 100644 GIT binary patch delta 57 zcmbQN(yzk1oR^o20SI<}=+4}+k=Kn?R@K=mCMC5jCMi`nCpkGWrno3MrZP3LC?&BZ LF=lfK>wF#n2xSvo delta 61 zcmeBInXJOQoR^o20SH_|J2N9U^187qYU*d?=cei>X6EMWC#CATfP!ozDXR4Vn_r diff --git a/src/yeardata/__pycache__/schema.cpython-311.pyc b/src/yeardata/__pycache__/schema.cpython-311.pyc index 8b3a86aca2a607127715bf7a8f468be13ebaddf6..f67b454b5342e3c8963f9385b66a1935c5cacdcc 100644 GIT binary patch delta 72 zcmbQB)T6|^oR^o20SK=7R%9OD$h(DIL)Fep0G#PI7XhesNKCQ|U(OVr diff --git a/test_masterdata_output.txt b/test_masterdata_output.txt new file mode 100644 index 0000000..96ab605 --- /dev/null +++ b/test_masterdata_output.txt @@ -0,0 +1,111 @@ +Traceback (most recent call last): + File "", line 198, in _run_module_as_main + File "", line 88, in _run_code + File "C:\dev\be-lcca\venv\Lib\site-packages\pytest\__main__.py", line 9, in + raise SystemExit(pytest.console_main()) + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 201, in console_main + code = main() + ^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 156, in main + config = _prepareconfig(args, plugins) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 341, in _prepareconfig + config = pluginmanager.hook.pytest_cmdline_parse( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_hooks.py", line 513, in __call__ + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_manager.py", line 120, in _hookexec + return self._inner_hookexec(hook_name, methods, kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 139, in _multicall + raise exception.with_traceback(exception.__traceback__) + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\helpconfig.py", line 105, in pytest_cmdline_parse + config = yield + ^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 103, in _multicall + res = hook_impl.function(*args) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1140, in pytest_cmdline_parse + self.parse(args) + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1494, in parse + self._preparse(args, addopts=addopts) + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1398, in _preparse + self.hook.pytest_load_initial_conftests( + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_hooks.py", line 513, in __call__ + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_manager.py", line 120, in _hookexec + return self._inner_hookexec(hook_name, methods, kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 139, in _multicall + raise exception.with_traceback(exception.__traceback__) + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\warnings.py", line 151, in pytest_load_initial_conftests + return (yield) + ^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\capture.py", line 154, in pytest_load_initial_conftests + yield + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 103, in _multicall + res = hook_impl.function(*args) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1222, in pytest_load_initial_conftests + self.pluginmanager._set_initial_conftests( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 581, in _set_initial_conftests + self._try_load_conftest( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 619, in _try_load_conftest + self._loadconftestmodules( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 659, in _loadconftestmodules + mod = self._importconftest( + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 710, in _importconftest + mod = import_path( + ^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\pathlib.py", line 587, in import_path + importlib.import_module(module_name) + File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\importlib\__init__.py", line 126, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "", line 1204, in _gcd_import + File "", line 1176, in _find_and_load + File "", line 1147, in _find_and_load_unlocked + File "", line 690, in _load_unlocked + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\assertion\rewrite.py", line 184, in exec_module + exec(co, module.__dict__) + File "C:\dev\be-lcca\tests\conftest.py", line 20, in + from fastapi import Request + File "C:\dev\be-lcca\venv\Lib\site-packages\fastapi\__init__.py", line 7, in + from .applications import FastAPI as FastAPI + File "C:\dev\be-lcca\venv\Lib\site-packages\fastapi\applications.py", line 16, in + from fastapi import routing + File "C:\dev\be-lcca\venv\Lib\site-packages\fastapi\routing.py", line 34, in + from fastapi.dependencies.models import Dependant + File "C:\dev\be-lcca\venv\Lib\site-packages\fastapi\dependencies\models.py", line 5, in + from fastapi.security.base import SecurityBase + File "C:\dev\be-lcca\venv\Lib\site-packages\fastapi\security\__init__.py", line 1, in + from .api_key import APIKeyCookie as APIKeyCookie + File "C:\dev\be-lcca\venv\Lib\site-packages\fastapi\security\api_key.py", line 6, in + from starlette.requests import Request + File "C:\dev\be-lcca\venv\Lib\site-packages\starlette\requests.py", line 12, in + from starlette.formparsers import FormParser, MultiPartException, MultiPartParser + File "C:\dev\be-lcca\venv\Lib\site-packages\starlette\formparsers.py", line 17, in + import python_multipart as multipart + File "C:\dev\be-lcca\venv\Lib\site-packages\python_multipart\__init__.py", line 7, in + from .multipart import ( + File "C:\dev\be-lcca\venv\Lib\site-packages\python_multipart\multipart.py", line 115, in + class MultipartState(IntEnum): + File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\enum.py", line 647, in __new__ + delattr(enum_class, '_singles_mask_') + File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\enum.py", line 752, in __delattr__ + super().__delattr__(attr) + ^^^^^^^ +KeyboardInterrupt diff --git a/test_masterdata_output_2.txt b/test_masterdata_output_2.txt new file mode 100644 index 0000000..67fb7e0 --- /dev/null +++ b/test_masterdata_output_2.txt @@ -0,0 +1,155 @@ +Traceback (most recent call last): + File "", line 198, in _run_module_as_main + File "", line 88, in _run_code + File "C:\dev\be-lcca\venv\Lib\site-packages\pytest\__main__.py", line 9, in + raise SystemExit(pytest.console_main()) + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 201, in console_main + code = main() + ^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 156, in main + config = _prepareconfig(args, plugins) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 341, in _prepareconfig + config = pluginmanager.hook.pytest_cmdline_parse( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_hooks.py", line 513, in __call__ + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_manager.py", line 120, in _hookexec + return self._inner_hookexec(hook_name, methods, kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 139, in _multicall + raise exception.with_traceback(exception.__traceback__) + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\helpconfig.py", line 105, in pytest_cmdline_parse + config = yield + ^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 103, in _multicall + res = hook_impl.function(*args) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1140, in pytest_cmdline_parse + self.parse(args) + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1494, in parse + self._preparse(args, addopts=addopts) + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1398, in _preparse + self.hook.pytest_load_initial_conftests( + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_hooks.py", line 513, in __call__ + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_manager.py", line 120, in _hookexec + return self._inner_hookexec(hook_name, methods, kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 139, in _multicall + raise exception.with_traceback(exception.__traceback__) + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\warnings.py", line 151, in pytest_load_initial_conftests + return (yield) + ^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\capture.py", line 154, in pytest_load_initial_conftests + yield + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 103, in _multicall + res = hook_impl.function(*args) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1222, in pytest_load_initial_conftests + self.pluginmanager._set_initial_conftests( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 581, in _set_initial_conftests + self._try_load_conftest( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 619, in _try_load_conftest + self._loadconftestmodules( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 659, in _loadconftestmodules + mod = self._importconftest( + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 710, in _importconftest + mod = import_path( + ^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\pathlib.py", line 587, in import_path + importlib.import_module(module_name) + File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\importlib\__init__.py", line 126, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "", line 1204, in _gcd_import + File "", line 1176, in _find_and_load + File "", line 1147, in _find_and_load_unlocked + File "", line 690, in _load_unlocked + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\assertion\rewrite.py", line 184, in exec_module + exec(co, module.__dict__) + File "C:\dev\be-lcca\tests\conftest.py", line 22, in + from src.main import app + File "C:\dev\be-lcca\src\main.py", line 33, in + from src.api import api_router + File "C:\dev\be-lcca\src\api.py", line 22, in + from src.simulations.router import router as simulations_router + File "C:\dev\be-lcca\src\simulations\__init__.py", line 1, in + from .router import router + File "C:\dev\be-lcca\src\simulations\router.py", line 17, in + from src.simulations.service import create, delete, get, get_all, run_simulation, update + File "C:\dev\be-lcca\src\simulations\service.py", line 34, in + column.key for column in sa_inspect(MasterData).mapper.column_attrs if column.key != "id" + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 1257, in __get__ + obj.__dict__[self.__name__] = result = self.fget(obj) + ^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\mapper.py", line 3172, in column_attrs + return self._filter_properties(properties.ColumnProperty) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\mapper.py", line 3225, in _filter_properties + self._check_configure() + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\mapper.py", line 2401, in _check_configure + _configure_registries({self.registry}, cascade=True) + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\mapper.py", line 4213, in _configure_registries + _do_configure_registries(registries, cascade) + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\mapper.py", line 4254, in _do_configure_registries + mapper._post_configure_properties() + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\mapper.py", line 2421, in _post_configure_properties + prop.post_instrument_class(self) + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\interfaces.py", line 1113, in post_instrument_class + self.strategy.init_class_attribute(mapper) + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\strategies.py", line 254, in init_class_attribute + _register_attribute( + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\strategies.py", line 126, in _register_attribute + desc = attributes.register_attribute_impl( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\attributes.py", line 2605, in register_attribute_impl + "_Dispatch[QueryableAttribute[Any]]", manager[key].dispatch + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\event\base.py", line 465, in __get__ + if hasattr(obj, "_slots_dispatch"): + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\attributes.py", line 472, in __getattr__ + return getattr(self.comparator, key) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 1332, in __getattr__ + return self._fallback_getattr(key) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\properties.py", line 472, in _fallback_getattr + return getattr(self.__clause_element__(), key) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 1319, in oneshot + result = fn(*args, **kw) + ^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\properties.py", line 439, in _memoized_method___clause_element__ + return self._orm_annotate_column(self.prop.columns[0]) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\orm\properties.py", line 425, in _orm_annotate_column + return col._annotate(annotations)._set_propagate_attrs( + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\sql\annotation.py", line 129, in _annotate + return Annotated._as_annotated_instance(self, values) # type: ignore + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\sql\annotation.py", line 277, in _as_annotated_instance + return cls(element, values) + ^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\sql\elements.py", line 5313, in __init__ + Annotated.__init__(self, element, values) + File "C:\dev\be-lcca\venv\Lib\site-packages\sqlalchemy\sql\annotation.py", line 289, in __init__ + self.__dict__ = element.__dict__.copy() + ^^^^^^^^^^^^^^^^^^^^^^^ +KeyboardInterrupt diff --git a/test_output.txt b/test_output.txt new file mode 100644 index 0000000..5acd846 --- /dev/null +++ b/test_output.txt @@ -0,0 +1,38 @@ +C:\dev\be-lcca\venv\Lib\site-packages\pytest_asyncio\plugin.py:247: PytestDeprecationWarning: The configuration option "asyncio_default_fixture_loop_scope" is unset. +The event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: "function", "class", "module", "package", "session" + + warnings.warn(PytestDeprecationWarning(_DEFAULT_FIXTURE_LOOP_SCOPE_UNSET)) +============================= test session starts ============================= +platform win32 -- Python 3.11.9, pytest-8.3.4, pluggy-1.5.0 -- C:\dev\be-lcca\venv\Scripts\python.exe +cachedir: .pytest_cache +rootdir: C:\dev\be-lcca +configfile: pyproject.toml +plugins: anyio-4.8.0, Faker-30.10.0, asyncio-1.3.0 +asyncio: mode=Mode.STRICT, debug=False, asyncio_default_fixture_loop_scope=None, asyncio_default_test_loop_scope=function +collecting ... collected 1 item + +tests/test_healthcheck.py::test_healthcheck PASSED [100%] + +============================== warnings summary =============================== +venv\Lib\site-packages\pydantic\_internal\_config.py:295 + C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_config.py:295: PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/ + warnings.warn(DEPRECATION_MESSAGE, DeprecationWarning) + +venv\Lib\site-packages\pydantic\fields.py:1042: 473 warnings + C:\dev\be-lcca\venv\Lib\site-packages\pydantic\fields.py:1042: PydanticDeprecatedSince20: Using extra keyword arguments on `Field` is deprecated and will be removed. Use `json_schema_extra` instead. (Extra keys: 'nullable'). Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/ + warn( + +venv\Lib\site-packages\pydantic\_internal\_generate_schema.py:297: 115 warnings + C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py:297: PydanticDeprecatedSince20: `json_encoders` is deprecated. See https://docs.pydantic.dev/2.10/concepts/serialization/#custom-serializers for alternatives. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.10/migration/ + warnings.warn( + +src\database\core.py:115 + C:\dev\be-lcca\src\database\core.py:115: MovedIn20Warning: The ``declarative_base()`` function is now available as sqlalchemy.orm.declarative_base(). (deprecated since: 2.0) (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9) + Base = declarative_base(cls=CustomBase) + +tests/test_healthcheck.py::test_healthcheck + C:\dev\be-lcca\venv\Lib\site-packages\httpx\_client.py:1437: DeprecationWarning: The 'app' shortcut is now deprecated. Use the explicit style 'transport=ASGITransport(app=...)' instead. + warnings.warn(message, DeprecationWarning) + +-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html +======================= 1 passed, 591 warnings in 0.95s ======================= diff --git a/test_output_e2e.txt b/test_output_e2e.txt new file mode 100644 index 0000000..2291833 --- /dev/null +++ b/test_output_e2e.txt @@ -0,0 +1,141 @@ +Traceback (most recent call last): + File "", line 198, in _run_module_as_main + File "", line 88, in _run_code + File "C:\dev\be-lcca\venv\Lib\site-packages\pytest\__main__.py", line 9, in + raise SystemExit(pytest.console_main()) + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 201, in console_main + code = main() + ^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 156, in main + config = _prepareconfig(args, plugins) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 341, in _prepareconfig + config = pluginmanager.hook.pytest_cmdline_parse( + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_hooks.py", line 513, in __call__ + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_manager.py", line 120, in _hookexec + return self._inner_hookexec(hook_name, methods, kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 139, in _multicall + raise exception.with_traceback(exception.__traceback__) + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\helpconfig.py", line 105, in pytest_cmdline_parse + config = yield + ^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 103, in _multicall + res = hook_impl.function(*args) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1140, in pytest_cmdline_parse + self.parse(args) + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1494, in parse + self._preparse(args, addopts=addopts) + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1398, in _preparse + self.hook.pytest_load_initial_conftests( + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_hooks.py", line 513, in __call__ + return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_manager.py", line 120, in _hookexec + return self._inner_hookexec(hook_name, methods, kwargs, firstresult) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 139, in _multicall + raise exception.with_traceback(exception.__traceback__) + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\warnings.py", line 151, in pytest_load_initial_conftests + return (yield) + ^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 122, in _multicall + teardown.throw(exception) # type: ignore[union-attr] + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\capture.py", line 154, in pytest_load_initial_conftests + yield + File "C:\dev\be-lcca\venv\Lib\site-packages\pluggy\_callers.py", line 103, in _multicall + res = hook_impl.function(*args) + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 1222, in pytest_load_initial_conftests + self.pluginmanager._set_initial_conftests( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 581, in _set_initial_conftests + self._try_load_conftest( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 619, in _try_load_conftest + self._loadconftestmodules( + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 659, in _loadconftestmodules + mod = self._importconftest( + ^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\config\__init__.py", line 710, in _importconftest + mod = import_path( + ^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\pathlib.py", line 587, in import_path + importlib.import_module(module_name) + File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\importlib\__init__.py", line 126, in import_module + return _bootstrap._gcd_import(name[level:], package, level) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "", line 1204, in _gcd_import + File "", line 1176, in _find_and_load + File "", line 1147, in _find_and_load_unlocked + File "", line 690, in _load_unlocked + File "C:\dev\be-lcca\venv\Lib\site-packages\_pytest\assertion\rewrite.py", line 184, in exec_module + exec(co, module.__dict__) + File "C:\dev\be-lcca\tests\conftest.py", line 22, in + from src.main import app + File "C:\dev\be-lcca\src\main.py", line 33, in + from src.api import api_router + File "C:\dev\be-lcca\src\api.py", line 18, in + from src.acquisition_cost.router import router as acquisition_data_router + File "C:\dev\be-lcca\src\acquisition_cost\router.py", line 6, in + from src.acquisition_cost.schema import AcquisitionCostDataPagination, AcquisitionCostDataRead, AcquisitionCostDataCreate, AcquisitionCostDataUpdate, ListQueryParams + File "C:\dev\be-lcca\src\acquisition_cost\schema.py", line 20, in + class AcquisitionCostDataCreate(AcquisitionCostDataBase): + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_model_construction.py", line 224, in __new__ + complete_model_class( + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_model_construction.py", line 602, in complete_model_class + schema = cls.__get_pydantic_core_schema__(cls, handler) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\main.py", line 702, in __get_pydantic_core_schema__ + return handler(source) + ^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 84, in __call__ + schema = self._handler(source_type) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 610, in generate_schema + schema = self._generate_schema_inner(obj) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 879, in _generate_schema_inner + return self._model_schema(obj) + ^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 691, in _model_schema + {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()}, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 691, in + {k: self._generate_md_field_schema(k, v, decorators) for k, v in fields.items()}, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1071, in _generate_md_field_schema + common_field = self._common_field_schema(name, field_info, decorators) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 1263, in _common_field_schema + schema = self._apply_annotations( + ^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 2056, in _apply_annotations + schema = get_inner_schema(source_type) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_schema_generation_shared.py", line 84, in __call__ + schema = self._handler(source_type) + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 2040, in inner_handler + metadata_js_function = _extract_get_pydantic_json_schema(obj, schema) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 2403, in _extract_get_pydantic_json_schema + return _extract_get_pydantic_json_schema(tp.__origin__, schema) + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\dev\be-lcca\venv\Lib\site-packages\pydantic\_internal\_generate_schema.py", line 2402, in _extract_get_pydantic_json_schema + if hasattr(tp, '__origin__') and not _typing_extra.is_annotated(tp): + ^^^^^^^^^^^^^^^^^^^^^^^^^ + File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2544.0_x64__qbz5n2kfra8p0\Lib\typing.py", line 470, in __getattr__ + def __getattr__(self, item): + +KeyboardInterrupt diff --git a/tests/conftest.py b/tests/conftest.py index 5ce6ed2..c6eb1a2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,18 +1,44 @@ +import os + +# Set dummy environment variables for testing +os.environ["DATABASE_HOSTNAME"] = "localhost" +os.environ["DATABASE_CREDENTIAL_USER"] = "test" +os.environ["DATABASE_CREDENTIAL_PASSWORD"] = "test" +os.environ["COLLECTOR_CREDENTIAL_USER"] = "test" +os.environ["COLLECTOR_CREDENTIAL_PASSWORD"] = "test" +os.environ["DEV_USERNAME"] = "test" +os.environ["DEV_PASSWORD"] = "test" + import asyncio from typing import AsyncGenerator, Generator import pytest -from httpx import AsyncClient +import pytest_asyncio +from httpx import AsyncClient, ASGITransport from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool +from fastapi import Request -import pytest -from sqlalchemy_utils import drop_database, database_exists -from starlette.config import environ -from starlette.testclient import TestClient +from src.main import app +from src.database.core import Base, get_db, get_collector_db +from src.auth.service import JWTBearer +from src.auth.model import UserBase -# from src.database import Base, get_db -# from src.main import app +# Import all models to register them with Base +import src.acquisition_cost.model +import src.equipment.model +import src.equipment_master.model +import src.manpower_cost.model +import src.manpower_master.model +import src.masterdata.model +import src.masterdata_simulations.model +import src.plant_fs_transaction_data.model +import src.plant_masterdata.model +import src.plant_transaction_data.model +import src.plant_transaction_data_simulations.model +import src.simulations.model +import src.uploaded_file.model +import src.yeardata.model # Test database URL TEST_DATABASE_URL = "sqlite+aiosqlite:///:memory:" @@ -23,7 +49,7 @@ engine = create_async_engine( poolclass=StaticPool, ) -async_session = sessionmaker( +TestingSessionLocal = sessionmaker( engine, class_=AsyncSession, expire_on_commit=False, @@ -31,39 +57,39 @@ async_session = sessionmaker( autoflush=False, ) - -async def override_get_db() -> AsyncGenerator[AsyncSession, None]: - async with async_session() as session: - try: - yield session - await session.commit() - except Exception: - await session.rollback() - raise - finally: - await session.close() - - -app.dependency_overrides[get_db] = override_get_db - - @pytest.fixture(scope="session") -def event_loop() -> Generator: - loop = asyncio.get_event_loop_policy().new_event_loop() +def event_loop(): + try: + loop = asyncio.get_running_loop() + except RuntimeError: + loop = asyncio.new_event_loop() yield loop - loop.close() - + # loop.close() # Avoid closing if it might be shared -@pytest.fixture(autouse=True) -async def setup_db() -> AsyncGenerator[None, None]: +@pytest_asyncio.fixture(autouse=True) +async def setup_db(): async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) yield async with engine.begin() as conn: await conn.run_sync(Base.metadata.drop_all) +async def override_get_db(request: Request = None): + async with TestingSessionLocal() as session: + yield session + +app.dependency_overrides[get_db] = override_get_db +app.dependency_overrides[get_collector_db] = override_get_db + +@pytest.fixture(autouse=True) +def mock_auth(monkeypatch): + async def mock_call(self, request: Request): + user = UserBase(user_id="test-id", name="test-user", role="admin") + request.state.user = user + return user + monkeypatch.setattr(JWTBearer, "__call__", mock_call) -@pytest.fixture +@pytest_asyncio.fixture async def client() -> AsyncGenerator[AsyncClient, None]: - async with AsyncClient(app=app, base_url="http://test") as client: + async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client: yield client \ No newline at end of file diff --git a/tests/database.py b/tests/database.py deleted file mode 100644 index 89b84ae..0000000 --- a/tests/database.py +++ /dev/null @@ -1,3 +0,0 @@ -from sqlalchemy.orm import scoped_session, sessionmaker - -Session = scoped_session(sessionmaker()) diff --git a/tests/e2e/test_acquisition_cost.py b/tests/e2e/test_acquisition_cost.py new file mode 100644 index 0000000..e748bbd --- /dev/null +++ b/tests/e2e/test_acquisition_cost.py @@ -0,0 +1,23 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_acquisition_costs(client: AsyncClient): + response = await client.get("/acquisition-data") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_create_acquisition_cost(client: AsyncClient): + payload = { + "assetnum": "TEST-ASSET", + "acquisition_cost": 1000.0, + "acquisition_year": 2024, + "residual_value": 100.0, + "useful_life": 10 + } + response = await client.post("/acquisition-data", json=payload) + # Note: This might fail if the schema requires more fields OR if those are valid but I'm missing some required ones. + # I'll check the schema if it fails, but for now I'll assume standard POST behavior. + assert response.status_code == 200 + assert response.json()["message"] == "Data created successfully" diff --git a/tests/e2e/test_equipment.py b/tests/e2e/test_equipment.py new file mode 100644 index 0000000..53eede2 --- /dev/null +++ b/tests/e2e/test_equipment.py @@ -0,0 +1,26 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_equipments(client: AsyncClient): + response = await client.get("/equipment") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_get_top_10_replacement_priorities(client: AsyncClient): + response = await client.get("/equipment/top-10-replacement-priorities") + assert response.status_code == 200 + assert response.json()["message"] == "Top 10 Replacement Priorities Data retrieved successfully" + +@pytest.mark.asyncio +async def test_get_top_10_economic_life(client: AsyncClient): + response = await client.get("/equipment/top-10-economic-life") + assert response.status_code == 200 + assert response.json()["message"] == "Top 10 Economic Life Data retrieved successfully" + +@pytest.mark.asyncio +async def test_count_remaining_life(client: AsyncClient): + response = await client.get("/equipment/count-remaining-life") + assert response.status_code == 200 + assert response.json()["message"] == "Count remaining life retrieved successfully" diff --git a/tests/e2e/test_equipment_master.py b/tests/e2e/test_equipment_master.py new file mode 100644 index 0000000..a75f10f --- /dev/null +++ b/tests/e2e/test_equipment_master.py @@ -0,0 +1,8 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_equipment_masters(client: AsyncClient): + response = await client.get("/equipment-master") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" diff --git a/tests/e2e/test_healthcheck.py b/tests/e2e/test_healthcheck.py new file mode 100644 index 0000000..0908cd7 --- /dev/null +++ b/tests/e2e/test_healthcheck.py @@ -0,0 +1,8 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_healthcheck(client: AsyncClient): + response = await client.get("/healthcheck") + assert response.status_code == 200 + assert response.json() == {"status": "ok"} diff --git a/tests/e2e/test_masterdata.py b/tests/e2e/test_masterdata.py new file mode 100644 index 0000000..aa4c215 --- /dev/null +++ b/tests/e2e/test_masterdata.py @@ -0,0 +1,97 @@ +import pytest +from httpx import AsyncClient +import uuid + +@pytest.mark.asyncio +async def test_create_masterdata(client: AsyncClient): + payload = { + "name": "Test Master Data", + "description": "Test Description", + "unit_of_measurement": "unit", + "value_num": 100.0, + "value_str": "100", + "seq": 1 + } + response = await client.post("/masterdata", json=payload) + assert response.status_code == 200 + data = response.json() + assert data["message"] == "Data created successfully" + assert data["data"]["name"] == "Test Master Data" + assert "id" in data["data"] + return data["data"]["id"] + +@pytest.mark.asyncio +async def test_get_masterdatas(client: AsyncClient): + # First create one + await client.post("/masterdata", json={ + "name": "Data 1", + "description": "Desc 1", + "unit_of_measurement": "u", + "value_num": 1.0, + "seq": 1 + }) + + response = await client.get("/masterdata") + assert response.status_code == 200 + data = response.json() + assert data["message"] == "Data retrieved successfully" + assert len(data["data"]["items"]) >= 1 + +@pytest.mark.asyncio +async def test_get_masterdata_by_id(client: AsyncClient): + # Create one + create_resp = await client.post("/masterdata", json={ + "name": "Data By ID", + "description": "Desc", + "unit_of_measurement": "u", + "value_num": 2.0, + "seq": 2 + }) + masterdata_id = create_resp.json()["data"]["id"] + + response = await client.get(f"/masterdata/{masterdata_id}") + assert response.status_code == 200 + assert response.json()["data"]["name"] == "Data By ID" + +@pytest.mark.asyncio +async def test_update_masterdata(client: AsyncClient): + # Create one + create_resp = await client.post("/masterdata", json={ + "name": "Old Name", + "description": "Desc", + "unit_of_measurement": "u", + "value_num": 3.0, + "seq": 3 + }) + masterdata_id = create_resp.json()["data"]["id"] + + # Update it + update_payload = { + "name": "New Name", + "value_num": 4.0 + } + response = await client.post(f"/masterdata/update/{masterdata_id}", json=update_payload) + assert response.status_code == 200 + assert response.json()["data"]["name"] == "New Name" + assert response.json()["data"]["value_num"] == 4.0 + +@pytest.mark.asyncio +async def test_delete_masterdata(client: AsyncClient): + # Create one + create_resp = await client.post("/masterdata", json={ + "name": "To Be Deleted", + "description": "Desc", + "unit_of_measurement": "u", + "value_num": 5.0, + "seq": 5 + }) + masterdata_id = create_resp.json()["data"]["id"] + + # Delete it + response = await client.post(f"/masterdata/delete/{masterdata_id}") + assert response.status_code == 200 + assert response.json()["message"] == "Data deleted successfully" + + # Verify it's gone + get_resp = await client.get(f"/masterdata/{masterdata_id}") + assert get_resp.status_code == 404 diff --git a/tests/e2e/test_masterdata_simulations.py b/tests/e2e/test_masterdata_simulations.py new file mode 100644 index 0000000..3037264 --- /dev/null +++ b/tests/e2e/test_masterdata_simulations.py @@ -0,0 +1,8 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_masterdata_simulations(client: AsyncClient): + response = await client.get("/masterdata-simulations") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" diff --git a/tests/e2e/test_plant_fs_transaction.py b/tests/e2e/test_plant_fs_transaction.py new file mode 100644 index 0000000..dbdc94e --- /dev/null +++ b/tests/e2e/test_plant_fs_transaction.py @@ -0,0 +1,16 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_list_fs_transactions(client: AsyncClient): + response = await client.get("/plant-fs-transaction-data") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_get_fs_charts(client: AsyncClient): + response = await client.get("/plant-fs-transaction-data/charts") + if response.status_code == 200: + assert "items" in response.json()["data"] + else: + assert response.status_code == 404 diff --git a/tests/e2e/test_plant_masterdata.py b/tests/e2e/test_plant_masterdata.py new file mode 100644 index 0000000..ea5f9a4 --- /dev/null +++ b/tests/e2e/test_plant_masterdata.py @@ -0,0 +1,20 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_plant_masterdatas(client: AsyncClient): + response = await client.get("/plant-masterdata") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_create_plant_masterdata(client: AsyncClient): + payload = { + "name": "Plant Parameter", + "description": "Plant Desc", + "unit_of_measurement": "unit", + "value_num": 10.5 + } + response = await client.post("/plant-masterdata", json=payload) + assert response.status_code == 200 + assert response.json()["message"] == "Data created successfully" diff --git a/tests/e2e/test_plant_transaction.py b/tests/e2e/test_plant_transaction.py new file mode 100644 index 0000000..5518e4a --- /dev/null +++ b/tests/e2e/test_plant_transaction.py @@ -0,0 +1,18 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_plant_transactions(client: AsyncClient): + response = await client.get("/plant-transaction-data") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_get_plant_charts(client: AsyncClient): + # This might return 404 if no data exists, but with my setup_db it should be empty + response = await client.get("/plant-transaction-data/charts") + # Actually, the service might raise 404 if it's empty + if response.status_code == 200: + assert "items" in response.json()["data"] + else: + assert response.status_code == 404 diff --git a/tests/e2e/test_simulation.py b/tests/e2e/test_simulation.py new file mode 100644 index 0000000..e44ba9f --- /dev/null +++ b/tests/e2e/test_simulation.py @@ -0,0 +1,19 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_simulations(client: AsyncClient): + response = await client.get("/simulations") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_create_simulation(client: AsyncClient): + payload = { + "label": "Test Simulation", + "description": "Test Desc", + "version": 1 + } + response = await client.post("/simulations", json=payload) + assert response.status_code == 200 + assert response.json()["data"]["label"] == "Test Simulation" diff --git a/tests/e2e/test_yeardata.py b/tests/e2e/test_yeardata.py new file mode 100644 index 0000000..b187bdd --- /dev/null +++ b/tests/e2e/test_yeardata.py @@ -0,0 +1,18 @@ +import pytest +from httpx import AsyncClient + +@pytest.mark.asyncio +async def test_get_yeardatas(client: AsyncClient): + response = await client.get("/yeardata") + assert response.status_code == 200 + assert response.json()["message"] == "Data retrieved successfully" + +@pytest.mark.asyncio +async def test_create_yeardata(client: AsyncClient): + payload = { + "year": 2024, + "description": "Test Year Data" + } + response = await client.post("/yeardata", json=payload) + assert response.status_code == 200 + assert response.json()["message"] == "Data created successfully" diff --git a/tests/factories.py b/tests/factories.py deleted file mode 100644 index 52ccd3d..0000000 --- a/tests/factories.py +++ /dev/null @@ -1,33 +0,0 @@ -import uuid -from datetime import datetime - -from factory import ( - LazyAttribute, - LazyFunction, - Sequence, - SubFactory, - post_generation, - SelfAttribute, -) -from factory.alchemy import SQLAlchemyModelFactory -from factory.fuzzy import FuzzyChoice, FuzzyDateTime, FuzzyInteger, FuzzyText -from faker import Faker -from faker.providers import misc -# from pytz import UTC - - -from .database import Session - -fake = Faker() -fake.add_provider(misc) - - -class BaseFactory(SQLAlchemyModelFactory): - """Base Factory.""" - - class Meta: - """Factory configuration.""" - - abstract = True - sqlalchemy_session = Session - sqlalchemy_session_persistence = "commit" diff --git a/tests/unit/test_masterdata_logic.py b/tests/unit/test_masterdata_logic.py new file mode 100644 index 0000000..fbb1da8 --- /dev/null +++ b/tests/unit/test_masterdata_logic.py @@ -0,0 +1,24 @@ +import pytest +from src.masterdata.service import calculate_pmt + +def test_calculate_pmt_zero_rate(): + # PMT = -PV / nper when rate is 0 + pv = 1000 + nper = 10 + rate = 0 + result = calculate_pmt(rate, nper, pv) + assert result == -100 + +def test_calculate_pmt_standard(): + # Example: Loan 1000, 5% rate, 2 periods + # PMT = -1000 * (0.05 * (1.05)^2) / ((1.05)^2 - 1) + # PMT = -1000 * (0.05 * 1.1025) / (0.1025) + # PMT = -1000 * (0.055125) / (0.1025) = -537.8048... + result = calculate_pmt(5, 2, 1000) + assert round(result, 2) == -537.80 + +def test_calculate_pmt_percentage(): + # If rate > 1, it divides by 100 + result_5 = calculate_pmt(5, 10, 1000) + result_05 = calculate_pmt(0.05, 10, 1000) + assert result_5 == result_05 diff --git a/tests/unit/test_masterdata_service.py b/tests/unit/test_masterdata_service.py new file mode 100644 index 0000000..b549f26 --- /dev/null +++ b/tests/unit/test_masterdata_service.py @@ -0,0 +1,37 @@ +import pytest +from unittest.mock import AsyncMock, MagicMock +from src.masterdata.service import create, get +from src.masterdata.schema import MasterDataCreate + +@pytest.mark.asyncio +async def test_create_masterdata_service(): + mock_db = AsyncMock() + masterdata_in = MasterDataCreate( + name="Test", + description="Desc", + unit_of_measurement="unit", + value_num=10.0, + seq=1 + ) + + result = await create(db_session=mock_db, masterdata_in=masterdata_in) + + assert result.name == "Test" + mock_db.add.assert_called_once() + mock_db.commit.assert_called_once() + +@pytest.mark.asyncio +async def test_get_masterdata_service(): + mock_db = AsyncMock() + mock_result = MagicMock() + mock_masterdata = MagicMock() + mock_masterdata.id = "test-id" + + # Mock behavior of db_session.execute().scalars().one_or_none() + mock_result.scalars.return_value.one_or_none.return_value = mock_masterdata + mock_db.execute.return_value = mock_result + + result = await get(db_session=mock_db, masterdata_id="test-id") + + assert result.id == "test-id" + mock_db.execute.assert_called_once()