Przejdź do treści

Wpis

Spec Driven Development w praktyce: jak zbudowalem pakowarke szkolen SCORM (MP4 -> SCORM 2004)

Opis, jak zbudowalem minimalna paczke SCORM 2004 z MP4, stosujac Spec Driven Development: wymagania, specyfikacje i plan testow.

ST

Stefan Tyllo

13 lutego 2026

· 7 min czytania
Wizualizacja sieci neuronowej

Spec Driven Development w praktyce: jak zbudowalem pakowarke szkolen SCORM (MP4 -> SCORM 2004)

Kiedy ktos mowi "zrobmy paczke SCORM", latwo wpasc w pulapke myslenia, ze to po prostu ZIP z index.html. Dopoki nie trafisz na pierwszy LMS, ktory jest bardziej "interpretacja standardu" niz standardem. Wtedy okazuje sie, ze najdrozsze nie jest napisanie kilku plikow HTML/JS, tylko dowiezienie przewidywalnego zachowania: manifest musi byc poprawny, runtime musi gadac z API, a completion i scoring musza sie zapisac dokladnie tak, jak oczekuje platforma.

Dlatego ten projekt zrobilem swiadomie w podejsciu Spec Driven Development (SDD): najpierw spisalem wymagania, potem specyfikacje zachowania, potem plan testow, a dopiero na koncu zaczalem implementacje. Efekt? Zamiast "dziala u mnie", dostalem paczke, ktora ma jasny kontrakt, jest testowalna i latwa do utrzymania.


Co wlasciwie budowalem

Celem byla minimalna, "developer-controlled" paczka SCORM 2004 3rd Edition, ktora:

  • uruchamia pojedyncza strone index.html,
  • odtwarza jedno lub wiecej MP4 z katalogu videos/,
  • zawiera test (10 pytan, 4 odpowiedzi, 1 poprawna) i prog zaliczenia 80%,
  • raportuje ukonczenie i wynik do LMS przez SCORM 2004 API (window.API_1484_11),
  • a po zaliczeniu wyswietla ekran ukonczenia i pozwala pobrac certyfikat jako PDF generowany po stronie przegladarki (tekst nakladany na PNG).

W wersji "manual" paczke skladam z gotowych statycznych plikow, a w wersji opcjonalnej mam generator w Next.js, ktory przyjmuje upload MP4 i metadane, sklada katalog zrodlowy i pakuje calosc.


Dlaczego SDD akurat tutaj zadzialalo

SCORM to specyficzna liga. Problemy zwykle nie wynikaja z braku funkcji, tylko z roznic interpretacyjnych miedzy LMS-ami oraz z "niewidzialnych" wymagan runtime: kolejnosc wywolan, wartosci statusow, commit w odpowiednim momencie, zachowanie na beforeunload.

W takim swiecie SDD jest jak pas bezpieczenstwa:

  1. Wymagania zamieniaja mgliste "ma dzialac w LMS" na liste zachowan, ktore da sie zweryfikowac.
  2. Specyfikacja zamienia wymagania w konkret: jakie pliki, jakie sciezki, jaki runtime flow.
  3. Plan testow daje mi procedure odbioru (SCORM Cloud / LMS), bez zgadywania.

To podejscie nie tylko redukuje ryzyko - ono przyspiesza, bo konczy dyskusje typu "czy to juz jest ukonczone?" albo "a czemu LMS nie widzi wyniku?".


Krok 1: wymagania jako kontrakt, nie lista zyczen

Zaczalem od spisania rzeczy, ktore maja byc prawda o produkcie. Bardzo konkretnie: standard (SCORM 2004 3rd Edition), struktura ZIP (manifest w root), launch file (index.html), MP4 w videos/, quiz 10 pytan i prog 80%, commit na ukonczenie i na unload oraz fallback, gdy API nie istnieje.

Dwa wymagania okazaly sie szczegolnie "game-changing":

  • "Jesli API SCORM nie istnieje, wideo nadal ma dzialac bez bledow."
    To brzmi jak detal, ale w praktyce wymusza defensywna architekture runtime i eliminuje klase awarii typu "ktos odpalil paczke lokalnie i wszystko sie wywalilo".

  • "Ekran ukonczenia i certyfikat tylko po zaliczeniu."
    Dzieki temu nie ma rozjazdu miedzy UI a tym, co raportuje do LMS. Jesli uzytkownik widzi "ukonczone", LMS tez dostaje passed/completed.

Wymagania ustawily granice: pojedyncze SCO, MP4-only, bez frameworkow w runtime (kompatybilnosc), a jesli mam serwery pomocnicze - porty 4000-4999.


Krok 2: specyfikacja - czyli jak to ma dzialac w srodku

W specyfikacji zalezalo mi na prostocie: SCO ma byc mozliwie statyczne i przewidywalne.

Minimalna paczka runtime

Docelowa struktura byla krotka i "oczywista":

  • index.html jako launch,
  • scripts/scorm-again.min.js i scripts/player.js (w tej kolejnosci),
  • videos/*.mp4,
  • oraz zasoby certyfikatu: assets/certificate.png, assets/certificate.json (uklad placeholderow), font assets/JaneAust.ttf.

To jest celowo "oldschoolowe": plain HTML + vanilla JS + natywny <video>. Bez routerow, bez bundli, bez zaleznosci runtime, ktore czasem robia LMS-om krzywde.

Kontrakt zachowania SCORM

Najwazniejszy fragment specyfikacji dotyczyl flow SCORM 2004:

  • Na window.load: sprobowac znalezc API (window.API_1484_11) i wykonac Initialize("").
  • Od razu ustawic minimum: cmi.completion_status="incomplete", cmi.exit="", potem Commit("").
  • Po ukonczeniu (test albo trigger zakonczenia wideo): ustawic scoring (raw/min/max/scaled) + completion_status="completed" + success_status="passed|failed", potem Commit("") i Terminate("").
  • Na beforeunload: wykonac Commit/Terminate raz (guard idempotentny), jesli sesja byla zainicjalizowana.

Brzmi prosto, ale to wlasnie ten "prostokat" wywolan jest sednem kompatybilnosci. I to byl jeden z najwiekszych zyskow z SDD: zanim napisalem linijke kodu, wiedzialem w jakich momentach i co dokladnie ma byc zapisane.


Krok 3: plan testow - moj "SCORM checklist", ktory konczy spory

Trzeci dokument to test plan. I szczerze: w projektach SCORM to czesto najwazniejsza czesc calej pracy.

Plan testow rozpisalem tak, zeby przejsc od rzeczy najbardziej podstawowych do najbardziej zdradliwych:

  • czy katalog zrodlowy ma wszystkie pliki (index.html, player.js, scorm-again, videos/*.mp4),
  • czy ZIP ma imsmanifest.xml w root i czy manifest wskazuje index.html,
  • czy kurs startuje w LMS bez bledow w konsoli,
  • czy quiz ma 10 pytan, pokazuje prog 80% i liczy wynik,
  • czy na starcie jest Initialize + incomplete + Commit,
  • czy po ukonczeniu sa ustawione score + statusy + Commit i Terminate,
  • czy po niezaliczeniu nie pojawia sie ekran ukonczenia,
  • czy beforeunload robi commit (bez dubli),
  • czy bez API (otwarcie lokalne) kurs dziala bez exceptionow.

To jest dokladnie ten moment, w ktorym SDD przestaje byc "ladna teoria" i staje sie narzedziem: kiedy LMS robi cos dziwnego, ja nie zgaduje - ja odpalam checkliste.


Implementacja: wypelnianie specyfikacji, a nie odkrywanie jej po drodze

Kiedy trzy artefakty byly gotowe, implementacja byla zaskakujaco spokojna. Nie budowalem "na czuja", tylko realizowalem konkretne zachowania.

Runtime "defensywny": dziala w LMS i dziala poza LMS

Najbardziej praktyczna decyzja to potraktowanie SCORM API jako opcjonalnego. W runtime to wyglada jak prosta zasada:

jezeli API jest - raportuj; jezeli nie ma - nie psuj doswiadczenia.

To bylo wymaganie wprost, wiec w kodzie wszystko, co SCORM-owe, jest opakowane tak, zeby brak API nie konczyl sie bledem.

Quiz i scoring: 80% jako jedno zrodlo prawdy

Quiz jest celowo "sztywny" (10 pytan, 4 opcje, 1 poprawna), a prog 80% jest pokazany przed startem. Po zakonczeniu wyswietlam wynik i pass/fail, a dopiero potem raportuje do LMS.

Dzieki temu UI i LMS maja spojna logike. Nie ma sytuacji, ze uzytkownik widzi "zaliczone", a LMS zapisuje "failed".

Certyfikat: maly feature, duza walidacja paczki

Certyfikat jest generowany client-side: tekst trafia na PNG zgodnie z ukladem placeholderow (JSON), a potem eksportuje to jako PDF do pobrania. To jest fajny element produktu, ale tez sprytna walidacja techniczna: jesli certyfikat dziala, to znaczy, ze assety sa poprawnie spakowane, sciezki sa poprawne, a runtime nie jest przesadnie "ciezki".


Pakowanie: manifest jako "miejsce, gdzie wszystko sie psuje" (wiec automatyzuje)

W SCORM najlatwiej przegrac na imsmanifest.xml: zla lokalizacja, zle namespacey, brak <file> dla assetu, niepoprawny href launch file. Dlatego w specyfikacji zalozylem, ze manifest jest auto-generowany przez simple-scorm-packager na podstawie katalogu zrodlowego.

W wariancie Next.js generator robi dokladnie to: sklada /tmp/scorm-source, wrzuca index.html, skrypty i MP4, a potem wywoluje packagera z wersja "2004 3rd Edition" i startingPage: "index.html", po czym streamuje ZIP do pobrania.

To podejscie jest pragmatyczne: nie chce recznie walczyc z XML-em, skoro moge testowac wynikowa paczke jako artefakt.


Co dalo mi SDD w tym projekcie (tak realnie)

Najwieksza korzysc nie byla "ladna dokumentacja". Najwieksza korzysc byla taka, ze:

  • z gory wiedzialem, co znaczy "done" (a nie negocjowalem tego po implementacji),
  • mialem testy, ktore tlumacza LMS-owi, co ma sie wydarzyc,
  • i moglem iterowac bez strachu, bo jesli cos zepsuje, test plan od razu pokaze, gdzie.

W SCORM to jest bezcenne, bo regresje czesto sa subtelne: jedna zmiana w runtime i nagle LMS przestaje zapisywac wynik - ale tylko w konkretnym flow.


Co zrobilbym jeszcze lepiej nastepnym razem

Dwie rzeczy, ktore widze jako naturalny upgrade:

  1. Jeszcze mocniej "produktowo" potraktowac trigger ukonczenia (koniec wideo vs koniec testu vs reczny przycisk) i zaprojektowac to jako swiadoma konfiguracje, bo to czesto zmienia sie na etapie wdrozenia. Specyfikacja juz dopuszcza konfiguracje triggera, ale warto to uczynic pierwszoplanowym elementem UI generatora.

  2. Dodac automatyczna walidacje "manifest <-> pliki" jako krok CI: rozpakuj ZIP, przeczytaj imsmanifest.xml, porownaj liste <file> z realnymi plikami. Test plan to opisuje, ale automatyzacja domknelaby temat w pelni.


Podsumowanie

Ten projekt byl dla mnie dobrym przypomnieniem, ze w SCORM sukces nie polega na tym, ze "strona sie otwiera". Sukces polega na tym, ze paczka ma przewidywalne zachowanie w LMS:

  • startuje,
  • raportuje,
  • nie sypie sie na unload,
  • i nie umiera, kiedy API nie jest dostepne.

Spec Driven Development bylo tu idealnym podejsciem: najpierw kontrakt (wymagania), potem mechanika (spec), potem dowod (test plan). Dopiero na koncu kod. I dokladnie tak powinno sie budowac rzeczy, ktore musza dzialac w cudzym ekosystemie.

Udostepnij

Podziel sie wpisem ze swoim zespolem.

Komentarze

0

Ładujemy komentarze...
Sprawdzamy logowanie...