|
| 1 | +\chapter{A \textit{SystemUnderTest}} |
| 2 | + |
| 3 | +A \textit{SystemUnderTest}, vagy röviden \textit{Sut}, a teszt keretrendszer interakcióját valósítja meg a tesztelés |
| 4 | +alatt álló fordítóprogrammal. Ez a komponens lehetőséget ad fordítóprgram futtatását személyre szabni. A különböző |
| 5 | +\textit{Sut} implementációk egy bővítmény betöltő rendszeren keresztül válnak elérhetőve a teszt keretrendszer számára. |
| 6 | + |
| 7 | +\section{A \textit{Sut} függvények} |
| 8 | + |
| 9 | + A \textit{Sut} implementáció gyakorlatilag négy absztrakt függvény megvalósítását jelenti, amelyeket az alábbi |
| 10 | + \textbf{\ref{fig:sut-functions}. ábra} mutat. A függvények argumentumait a tömörség érdekében elhagytam. |
| 11 | + |
| 12 | + \begin{figure}[ht] |
| 13 | + \centering |
| 14 | + \begin{minted}{python} |
| 15 | +class Sut(ABC): |
| 16 | + @abstractmethod |
| 17 | + async def setup(self, ...) -> SubprocessResult: ... |
| 18 | + |
| 19 | + @abstractmethod |
| 20 | + async def compile(self, ...) -> SubprocessResult: ... |
| 21 | + |
| 22 | + @abstractmethod |
| 23 | + async def link(self, ...) -> SubprocessResult: ... |
| 24 | + |
| 25 | + @abstractmethod |
| 26 | + async def run(self, ...) -> SubprocessResult: ... |
| 27 | + \end{minted} |
| 28 | + \caption{\label{fig:sut-functions} A \textit{Sut} absztrakt függvényei} |
| 29 | + \end{figure} |
| 30 | + |
| 31 | + A lépések a definíciós sorrendjében vannak végrehajtva. |
| 32 | + |
| 33 | + Az első \textit{setup} lépés lehetővé teszi a tesztfuttatás előtt extra lépéseket végrehajtani, például fájlokat |
| 34 | + létrehozni, környezeti változókat beállítani, vagy akár extra függvénykönyvtárakat is elérhetővé lehet tenni a |
| 35 | + fordítóprogram számára. Az ezt követő lépések opcionálisak, a tesztesetek típusától függenek. |
| 36 | + |
| 37 | + A második \textit{compile} lépésben történik a tesztesetek fordítása. Itt lehet személyre szabni a fordítóprogram |
| 38 | + számára átadott parancssori argumentumokat, amiket a \textit{ConfigManager} objektum előállított. Itt még történhet |
| 39 | + transzformáció a paramétereken, de egy kanonikus implementáció csak az argumentumok megfelelő sorrendjét állítja |
| 40 | + elő. |
| 41 | + |
| 42 | + A harmadik \textit{link} lépésben a szerkesztés, \textit{(idegen szóval linkelés)} történik. Itt ad lehetőseg a |
| 43 | + rendszer a fordítóprogram szerkeszőjének parancssori argumentumait beállítani. |
| 44 | + |
| 45 | + A negyedik \textit{run} lépésben a fordítoprgram kimenetét lehet futtatni egy arra alkalmas szimultáro programban, |
| 46 | + vagy akár a végrehajtó gépen direktben. |
| 47 | + |
| 48 | + Fontos kiemelni, hogy bár ezek a függvények egymás után vannak végrehajtva, nincs megkötve hogy a tényleges |
| 49 | + implementációk milyen fordítóprogram invokációkat állítanak össze. Például ki is hagyhatnak lépéseket. |
| 50 | + |
| 51 | +\section{A \textit{CacheTarget} rendszer} |
| 52 | + |
| 53 | + A \textit{CacheTarget} rendszer lehetőséget ad a \textit{Sutok} \textit{run} függvényei számára hogy eredményeiket |
| 54 | + egy gyorsítótárba helyezzék. Ez a gyorsítótár gyakorlatilag egy \textit{SQLite} adatbázis ahol egy kalkulált |
| 55 | + \textit{hashhez} hozzá van rendelve a futás eredménye. |
| 56 | + |
| 57 | + A rendszer olyan fordítóprogramokkal működik amelyek kimenetében \textit{ELF} formátumú tárgykódot generálnak. A |
| 58 | + rendszer megvizsgálja a kimeneti \textit{ELF} fájl fejlécét és szegmenseit és aggregálja a bájtokat. Ehhez az |
| 59 | + aggregációhioz még hozzáveszi a fordítoprgram bementi argumentumai és a \textit{STDIN} bementére érkező bájtokat, |
| 60 | + majd a végeredményből egy \textit{SHA-512 hasht}~\cite{sha512} generál. |
| 61 | + |
| 62 | + Az adatbázis ezt a \textit{hasht} és futáseredményt az alábbi \textbf{\ref{fig:cache-schema}. ábrán} látható |
| 63 | + táblában tárolja. |
| 64 | + |
| 65 | + \begin{figure}[ht] |
| 66 | + \centering |
| 67 | + \begin{tabular}{ll} |
| 68 | + \toprule |
| 69 | + \multicolumn{2}{c}{\textit{CacheTable}} \\ |
| 70 | + \cmidrule{1-2} |
| 71 | + SQL type & Name \\ |
| 72 | + \midrule |
| 73 | + \textit{TEXT} & test\_case \\ |
| 74 | + \textit{TEXT} & hash \\ |
| 75 | + \textit{TEXT} & argv \\ |
| 76 | + \textit{TEXT} & stdin \\ |
| 77 | + \textit{INTEGER} & timeout \\ |
| 78 | + \textit{TEXT} & stdout \\ |
| 79 | + \textit{INTEGER} & exit\_code \\ |
| 80 | + \textit{TEXT} & stderr \\ |
| 81 | + \textit{INTEGER} & elapsed\_time \\ |
| 82 | + \bottomrule |
| 83 | + \end{tabular} |
| 84 | + \caption{\label{fig:cache-schema} A \textit{CacheTarget} adatbázis séma} |
| 85 | + \end{figure} |
| 86 | + |
| 87 | + A rendszer előnye, hogy a sokáig tartó futtatandó tesztesetek futásidejét drasztikusan tudja csökkenteni. |
| 88 | + Kifejezetten akkor a leghasznosabb ha a kimeneti \textit{ELF} futtatható szimulátroban fut, mert a szimulátorok |
| 89 | + természetükből adódóan lassabbak mint egy natív futtatás. |
| 90 | + |
| 91 | + A rendszer hátránya azonban az, hogy az elosztott futtatás során a kliensek nem osztják meg a gyorsítótáraikat |
| 92 | + egymással, ugyanis azok lemezen, \textit{SQLite} adatbázisokban vannak tárolva. Ha a futás során a szerver úgy |
| 93 | + osztja ki a teszteseteket, hogy egyik kliensen sem kerülne futtatásra ugyan az a teszt különböző tesztcsomagokból, |
| 94 | + akkor gyakorlatilag haszontalan arra a futásra. |
| 95 | + |
| 96 | + Ugyanakkor a kliensek megtarthatják a gyorsítótáraikat így jövőbeli futások alkalmával hasznosíthatóak. |
| 97 | + |
| 98 | +\section{A bővítmény rendszer} |
| 99 | + |
| 100 | + A \textit{Sut} komponensek dinamikusan kerülnek betöltésre. Ez lehetővé teszi, hogy a teszt keretrendszer csomagán |
| 101 | + kívülről is definiálható legyen egy \textit{Sut}. Ez a folyamat két lépésből áll, először regisztrálni kell a |
| 102 | + bővítményeket, majd be kell őket tölteni a \textit{Pythonban} szabványos \textit{importlib} rendszeren keresztül |
| 103 | + |
| 104 | + \subsection{Bővítmény regisztráció} |
| 105 | + |
| 106 | + Ennek megvalósítására a \textit{Python} nyelv által nyújtott \textit{metaclass} konstrukciót alkalmazta. |
| 107 | + |
| 108 | + A \textit{Python metclassok} egy fajta futásidejű formái a metaprogramozásnak, tehát futásidőben lehet a |
| 109 | + típusokat manipluálni. A bővítmény rendszer úgy használja fel ezt a konstrukciót, hogy amikor egy \textit{Sut} |
| 110 | + implementáció örököl a \textit{Sut} ősosztályból, akkor az ősosztály feljegyzi azt a típust egy asszociatív |
| 111 | + adatstruktúrába. |
| 112 | + |
| 113 | + Régebbi \textit{Python} verziókban szükségszerűen definiálni kellett egy osztályt ami a \textit{type} beépített |
| 114 | + típusból örökölt. Azonban sokkal elegánsabb és újabb megoldás az \\ \verb|__init_subclass__| függvény. A |
| 115 | + \textbf{\ref{fig:subclass-hook}. ábrán} látható ennek implementációja. |
| 116 | + |
| 117 | + \begin{figure}[ht] |
| 118 | + \centering |
| 119 | + \begin{minted}{python} |
| 120 | +class Sut(ABC): |
| 121 | + def __init_subclass__(cls, target_name: str, **kwargs: Any) -> None: |
| 122 | + super().__init_subclass__(**kwargs) |
| 123 | + cls._SUBCLASSES[target_name] = cls # storing the child class |
| 124 | + |
| 125 | + @classmethod |
| 126 | + def get_plugin(cls, target_name: str) -> type["Sut"] | None: |
| 127 | + return cls._SUBCLASSES.get(target_name) |
| 128 | + \end{minted} |
| 129 | + \caption{\label{fig:subclass-hook} A bővítmény regisztrálás implementációja} |
| 130 | + \end{figure} |
| 131 | + |
| 132 | + A \textit{Sut} implementációknak egyszerűen annyi dolguk van, hogy az öröklés során tovább adják a |
| 133 | + \verb|target_name| nevesített paramétert az ősosztálynak. |
| 134 | + |
| 135 | + \subsection{Bővítmény betöltés} |
| 136 | + |
| 137 | + A bővítmény betöltés a \textit{SutPluginLoader} osztályon keresztül történik. A bővítmény kezelő a bejövő modul |
| 138 | + mappájában egy \textit{ssplugin.py} nevű fájlt keres. Mivel a bővítmények szabványos \textit{Python} comagok |
| 139 | + így nem elég csupán az elérési útvonalát ismerni a bővítmény fájlnak, hanem végre is kell hajtani azt. |
| 140 | + |
| 141 | + Erre többek között azért van szükség mert a \textit{Python} dinamikus így ameddig egy fájl nincs betöltve, |
| 142 | + addig a benne lévő definíciók nem is léteznek. Továbbá a globális szkópban lévő kódot is futtatni kell különben |
| 143 | + a modul használhatatlan lenne. A modul betöltését és végrehajtást a \textbf{\ref{fig:module-loder}. ábra} |
| 144 | + mutatja be. |
| 145 | + |
| 146 | + \begin{figure}[ht] |
| 147 | + \centering |
| 148 | + \begin{minted}{python} |
| 149 | +class SutPluginLoader: |
| 150 | + def _load_module(self) -> None: |
| 151 | + # Error handling code omitted for brevity ... |
| 152 | + td: Final = self.target_dir |
| 153 | + spec: Final = spec_from_file_location( |
| 154 | + name=f"{td.parent.name}.{td.name}.ssplugin", |
| 155 | + location=td / "ssplugin.py", |
| 156 | + ) |
| 157 | + module: Final = module_from_spec(spec) |
| 158 | + loader.exec_module(module) |
| 159 | + |
| 160 | + def load_sut_plugin(self) -> type[Sut]: |
| 161 | + self._load_module() |
| 162 | + if (plugin := Sut.get_plugin(self.target_dir.name)) is not None: |
| 163 | + return plugin |
| 164 | + # Error handling code omitted for brevity ... |
| 165 | + \end{minted} |
| 166 | + \caption{\label{fig:module-loder} A \textit{SutPluginLoader} implementációja.} |
| 167 | + \end{figure} |
| 168 | + |
| 169 | + A \verb|SutPluginLoader.load_sut_plgin| függvényével megkapjuk a dinamikusan betöltött \textit{Sut} |
| 170 | + implementációt. |
| 171 | + |
| 172 | +\section{Összegzés} |
| 173 | + |
| 174 | + Összességében a \textit{SystemUnderTest} egy nagyon funkciókban gazdag alrendszere a teszt keretrendszernek. A |
| 175 | + gyorsítótár implementációját leszámítva, az alkotó komponensei, koncepciójukat tekintve generikusak. |
| 176 | + |
| 177 | + A teszt kreterendszer nem tartalmaz olyan beépített bővítményt amely ne egy fordítóprogramot kezelne, ugyanakkor |
| 178 | + könnyen megvalósítható egy olyan \textit{Sut} bővítmény implementáció, amely nem csak fordítóprogramot tud |
| 179 | + tesztelni, hanem bármilyen parancssorból vezérelhető programot. |
| 180 | + |
| 181 | + Egy kézenfekvő példa egy \LaTeX{} fordítóprogramot tesztelő \textit{Sut} bővítmény. |
| 182 | + |
| 183 | + \begin{enumerate} |
| 184 | + \item A bővítmény a \textit{setup} lépésben beállítja megfelelő munka könyvtárat ugyanis a dokumentum fordítók |
| 185 | + erre érzkények. |
| 186 | + \item A \textit{compile} lépésben végrehajtaj az első futást ahol a referenciák még üresek. |
| 187 | + \item A \textit{link} lépésben végrehajtja a második futást ahol elkészül a teljes dokumentum \textit{DVI} vagy |
| 188 | + \textit{PDF} formátumban. |
| 189 | + \item A \textit{run} lépésben pedig egy nyelvtani korrektor program ellenőrzi a generált dokumentumot. |
| 190 | + \end{enumerate} |
0 commit comments