Wyniki egzaminu

Informacje o egzaminie:
  • Zawód: Technik programista
  • Kwalifikacja: INF.04 - Projektowanie, programowanie i testowanie aplikacji
  • Data rozpoczęcia: 8 czerwca 2026 13:40
  • Data zakończenia: 8 czerwca 2026 14:02

Egzamin zdany!

Wynik: 33/40 punktów (82,5%)

Wymagane minimum: 20 punktów (50%)

Nowe
Analiza przebiegu egzaminu- sprawdź jak rozwiązywałeś pytania
Pochwal się swoim wynikiem!
Szczegółowe wyniki:
Pytanie 1

W języku Java wyjątek ArrayIndexOutOfBoundsException występuje, gdy następuje próba dostępu do elementu tablicy, którego

A. wartość przekracza rozmiar tablicy
B. indeks jest równy lub większy od rozmiaru tablicy
C. wartość przewyższa jego indeks
D. indeks mieści się w zakresie od 0 do n-1, gdzie n oznacza rozmiar tablicy
Wyjątek ArrayIndexOutOfBoundsException w Javie to taki klasyk, na który łatwo się naciąć, zwłaszcza gdy operujesz na tablicach dynamicznie lub masz jakieś pętle i zapomnisz o poprawnych granicach. Ta odpowiedź jest prawidłowa, bo w języku Java indeksowanie tablic zaczyna się od 0, a ostatni poprawny indeks to zawsze rozmiar tablicy minus jeden. Jeśli próbujesz dostać się do elementu, którego indeks jest równy lub większy od rozmiaru tablicy, silnik uruchomieniowy Javy od razu rzuci ten wyjątek. Przykład? Masz tablicę int[] t = new int[5]; i próbujesz odwołać się do t[5] albo t[10] – nie zadziała, bo legalne są tylko indeksy 0, 1, 2, 3, 4. Moim zdaniem to jeden z tych wyjątków, które wyraźnie pokazują, jak ważne jest zabezpieczanie kodu i stosowanie praktyk takich jak sprawdzanie długości tablicy przed dostępem do jej elementów. W profesjonalnym kodzie, zwłaszcza komercyjnym, nie zostawia się takich rzeczy przypadkowi – często stosuje się pętle typu for (int i = 0; i < array.length; i++), żeby mieć pewność, że nigdzie nie wyjedziemy poza zakres. Dobra praktyka to też wykorzystywanie narzędzi jak testy jednostkowe, żeby wyłapywać takie błędy. Warto pamiętać, że ten wyjątek jest unchecked, czyli nie musisz go łapać w kodzie, ale dobrze jest rozumieć, że jego pojawienie się oznacza błąd w logice programu. Osobiście uważam, że jeśli ktoś raz się na tym przejedzie, to już zawsze sprawdza rozmiar tablicy przed dostępem – taka nauczka na całe życie programisty.

Pytanie 2

Jakie z wymienionych narzędzi jest szeroko stosowane do debugowania aplikacji internetowych?

A. Git
B. Postman
C. Chrome DevTools
D. Blender
Chrome DevTools to potężne narzędzie wbudowane w przeglądarkę Google Chrome, które umożliwia debugowanie aplikacji webowych. Umożliwia ono analizowanie struktury DOM, monitorowanie sieci, profilowanie wydajności oraz inspekcję kodu JavaScript. Chrome DevTools pozwala na śledzenie błędów w czasie rzeczywistym, edytowanie stylów CSS oraz modyfikowanie HTML bezpośrednio w przeglądarce, co znacznie przyspiesza proces rozwoju i testowania aplikacji webowych.

Pytanie 3

Który z wymienionych poniżej przykładów ilustruje prawidłowy szkielet zarządzania wyjątkami w języku C++?

A. try { kod } finally { obsługa }
B. try { kod } handle { obsługa }
C. try { kod } except { obsługa }
D. try { kod } catch { obsługa }
Niestety, skrypt 'try { kod } handle { obsługa }' nie zadziała w C++. Słowo 'handle' nie jest czymś, co znajdziesz w tym języku – używamy 'catch'. Poza tym, 'except' to termin z Pythona, nie C++. No i 'finally' też nie istnieje w C++, to też jest z języków jak Java czy Python, które mają to w inny sposób. Tak że jedynym poprawnym rozwiązaniem w C++ jest właśnie 'try' i 'catch'. Tylko to gwarantuje, że wszystko będzie działać jak należy.

Pytanie 4

Który z wymienionych procesów NIE jest częścią etapu kompilacji?

A. Tłumaczenie kodu źródłowego na język maszynowy
B. Analiza działania programu w czasie rzeczywistym
C. Optymalizacja kodu
D. Weryfikacja błędów składniowych
Analiza działania programu w czasie rzeczywistym nie należy do etapu kompilacji, lecz do etapu wykonywania programu. Kompilacja obejmuje tłumaczenie kodu źródłowego na język maszynowy, optymalizację kodu i weryfikację błędów składniowych. Analiza w czasie rzeczywistym to rola debuggera, który działa na uruchomionym programie i umożliwia śledzenie jego działania krok po kroku.

Pytanie 5

Testy mające na celu identyfikację błędów w interfejsach między modułami bądź systemami nazywane są testami

A. jednostkowymi
B. bezpieczeństwa
C. integracyjnymi
D. wydajnościowymi
Testy integracyjne mają na celu wykrycie błędów w interfejsach i połączeniach między modułami lub systemami. Głównym celem tych testów jest sprawdzenie, czy różne komponenty aplikacji współpracują ze sobą zgodnie z oczekiwaniami. Testy integracyjne są przeprowadzane po testach jednostkowych, ale przed testami systemowymi. W praktyce testy te obejmują scenariusze, w których kilka modułów wymienia dane lub współdziała w ramach wspólnego procesu. Integracja jest kluczowa dla zapewnienia, że cały system działa jako spójna całość, co minimalizuje ryzyko błędów na etapie produkcji i poprawia jakość końcowego produktu. Przykładem może być test komunikacji między modułem autoryzacji użytkowników a modułem płatności w aplikacji e-commerce.

Pytanie 6

W jakiej fazie cyklu życia projektu informatycznego następuje integracja oraz testowanie wszystkich modułów systemu?

A. Etap planowania
B. Etap implementacji
C. Faza analizy
D. Faza wdrożenia
Faza implementacji to etap cyklu życia projektu informatycznego, w którym następuje integracja i testowanie wszystkich modułów systemu. Po zakończeniu fazy projektowania i programowania, elementy aplikacji są łączone w jeden spójny system. Integracja polega na połączeniu komponentów, co umożliwia sprawdzenie ich współpracy oraz poprawności przepływu danych. Następnie przeprowadzane są testy integracyjne i systemowe, których celem jest wykrycie błędów w interakcji między modułami. Proces ten jest niezbędny, aby zapewnić stabilność aplikacji przed wdrożeniem do środowiska produkcyjnego. Skuteczna integracja minimalizuje ryzyko awarii i zwiększa niezawodność systemu.

Pytanie 7

Wykorzystując jeden z dwóch zaprezentowanych sposobów inkrementacji w językach z rodziny C lub Java, można zauważyć, że
Zapis pierwszy:

b = a++;
Zapis drugi:
b = ++a;
A. Drugi zapis nie jest zgodny ze składnią, co doprowadzi do błędów kompilacji.
B. Wartość zmiennej b będzie wyższa po użyciu drugiego zapisu w porównaniu do pierwszego.
C. Tylko przy użyciu pierwszego zapisu zmienna a zostanie zwiększona o 1.
D. Bez względu na zastosowany sposób, w zmiennej b zawsze uzyskamy ten sam rezultat.
W językach programowania z rodziny C (w tym C++ i Java) istnieją dwie formy inkrementacji: preinkrementacja (++x) i postinkrementacja (x++). Preinkrementacja zwiększa wartość zmiennej przed jej użyciem w wyrażeniu, natomiast postinkrementacja zwiększa ją dopiero po zakończeniu aktualnej operacji. Oznacza to, że w przypadku postinkrementacji, wartość zmiennej przed zwiększeniem zostanie użyta w bieżącym wyrażeniu, a dopiero potem następuje jej zwiększenie o 1. Ta subtelna różnica ma istotne znaczenie, zwłaszcza w pętlach i wyrażeniach logicznych, gdzie każda iteracja wpływa na wynik. W praktyce preinkrementacja jest nieco bardziej efektywna, ponieważ nie wymaga przechowywania kopii pierwotnej wartości zmiennej, co przekłada się na minimalnie lepszą wydajność w niektórych przypadkach.

Pytanie 8

Kod funkcji "wykonaj()" przedstawiony poniżej weryfikuje, czy

bool wykonaj(int argument)
{
    int T[] = {4, 15, -2, 9, 202};
    for(int i=0; i<5; i++) {
        if(T[i] == argument)
            return true;
    }
    return false;
}
A. konkretny element (argument) jest obecny w tablicy liczb całkowitych
B. przekazany argument mieści się w zakresie od 0 do 4
C. w tablicy liczb całkowitych znajdują się jedynie wartości 4, 15, -2, 9, 202
D. wszystkie elementy w tablicy są równe wartości przekazanego argumentu
Funkcja wykonaj() została napisana tak, by sprawdzić, czy przekazany do niej argument znajduje się w konkretnej tablicy liczb całkowitych. To bardzo typowy sposób wyszukiwania wartości w niewielkich zbiorach – pętla przechodzi przez każdy element tablicy i jeśli napotka element równy argumentowi, natychmiast zwraca true. To klasyczna implementacja tzw. liniowego wyszukiwania (linear search), co moim zdaniem jest często spotykane w zadaniach rekrutacyjnych albo przy szybkim prototypowaniu. W praktyce, jeśli tablica byłaby większa albo wymagania dotyczące wydajności byłyby bardziej rygorystyczne, lepiej jest korzystać z innych struktur danych, np. std::set czy std::unordered_set, gdzie operacja wyszukiwania jest zazwyczaj szybsza. Ale tutaj – dla kilku liczb – ta metoda wystarcza i jest czytelna. Warto zauważyć, że taki kod pozwala na szybkie sprawdzenie obecności dowolnego elementu w małej kolekcji i nie wymaga jej sortowania. Z mojego doświadczenia, rozumienie tego mechanizmu pomaga potem w nauce bardziej zaawansowanych algorytmów przeszukiwania i ogólnie usprawnia myślenie algorytmiczne. W codziennej pracy programisty znajomość takich podstaw bardzo się przydaje, bo często trzeba „na szybko” sprawdzić, czy coś znajduje się w tablicy lub liście. Warto też pamiętać, żeby nie nadużywać takich rozwiązań przy dużych ilościach danych – wtedy zaczynają się schody z wydajnością. Ale podsumowując, ta odpowiedź dokładnie opisuje, co robi ten kod – po prostu sprawdza, czy argument jest obecny w zbiorze liczb.

Pytanie 9

Jaki będzie wynik działania poniższego kodu w języku Java?

String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a.equals(c));
A. true, true, true
B. true, false, false
C. false, false, true
D. true, false, true
Wyniki, które wskazują, że zarówno porównanie 'a == c', jak i 'a.equals(c)' powinny zwracać 'true', opierają się na błędnym zrozumieniu, jak działa porównywanie obiektów w Javie. Warto zrozumieć, że operator '==' sprawdza, czy dwie referencje wskazują na ten sam obiekt w pamięci. W przypadku zmiennych 'a' i 'b', ponieważ obie są literałami tego samego ciągu, JVM optymalizuje ich przechowywanie, co skutkuje, że obie referencje prowadzą do tego samego obiektu. Natomiast zmienna 'c', utworzona za pomocą 'new String()', to zupełnie inny obiekt, mimo że jego wartość jest taka sama jak w 'a'. W związku z tym porównanie 'a == c' zwraca false. Z kolei metoda 'equals()' jest zaprojektowana do porównania wartości, a nie referencji, co oznacza, że 'a.equals(c)' zwróci true, ponieważ obie zmienne mają tę samą zawartość. Zrozumienie tych zasad jest kluczowe, aby unikać typowych pułapek przy pracy z obiektami w Javie. Pamiętaj, aby zawsze preferować 'equals()' do porównywania stringów i innych obiektów, aby uzyskać prawidłowe wyniki.”

Pytanie 10

W zaprezentowanym fragmencie kodu występuje błąd logiczny. Na czym on polega?

int x = 0;
while (x != 0 || x != 5) {
  std::cout << x << " ";
  x++;
}
A. Nieprawidłowym warunku pętli, który sprawia, że pętla jest nieskończona.
B. Niewłaściwym warunku pętli, co powoduje, że pętla nigdy się nie wykona.
C. Niepoprawnym użyciu funkcji cout, co skutkuje tym, że zmienna jest wczytywana w pętli.
D. Braku zainicjowania zmiennej x, co powoduje, że zmienna nie ma wartości początkowej.
Nieprawidłowy warunek pętli powoduje, że staje się ona nieskończona, co jest częstym problemem w programowaniu. W tym przypadku warunek while(x != 0 || x != 5) jest zawsze prawdziwy, ponieważ dla każdej wartości x, która nie jest jednocześnie równa 0 i 5, pętla nigdy się nie zakończy. To logiczny błąd, ponieważ zmienna x nigdy nie osiągnie stanu, w którym oba warunki będą jednocześnie fałszywe. W praktyce powinno się stosować warunki logiczne, które mogą stać się fałszywe dla jakiegoś stanu zmiennych, co pozwala pętli zakończyć działanie. Częstym wzorcem jest użycie operatora && zamiast ||, aby sprawdzić, czy zmienna osiągnęła konkretny zakres wartości. W ten sposób można zagwarantować, że program nie wejdzie w nieskończoną pętlę. Tego typu błędy są często wykrywane podczas testowania i debugowania kodu, a ich unikanie jest kluczowe w zapewnieniu poprawnego działania aplikacji. Dobre praktyki obejmują dokładne przemyślenie warunków pętli i testowanie ich w różnych scenariuszach.

Pytanie 11

Na schemacie widoczny jest fragment diagramu blokowego pewnego algorytmu. Ile razy zostanie zweryfikowany warunek n<7?

Ilustracja do pytania
A. 6
B. 8
C. 7
D. 5
Wartość 8 pokazuje, że chyba źle zrozumiałeś, jak działa liczba iteracji. Pojawiły się dodatkowe porównania, które nie powinny się zdarzyć w pętli. A wynik 5 może być przez to, że pętla zakończyła się za szybko, albo myślałeś, że zmienna zaczyna się z innej wartości. Z kolei 7 to już za dużo iteracji, co nie pasuje do standardowego działania pętli warunkowej.

Pytanie 12

Jakie aspekty powinny być brane pod uwagę przy tworzeniu zestawów danych?

A. Typ zastosowanego kompilatora
B. Ilość linii kodu programu
C. Narzędzia do analizy błędów
D. Metoda alokacji pamięci dla danych
Sposób alokacji pamięci dla danych to kluczowy element projektowania zestawów danych, ponieważ wpływa na wydajność i efektywność programu. Dynamiczna alokacja pamięci pozwala na tworzenie struktur, których rozmiar jest zmienny i dostosowuje się w trakcie działania aplikacji. Dzięki temu programiści mogą optymalnie zarządzać zasobami systemowymi, unikając marnowania pamięci lub jej niedoboru. Wybór odpowiedniej metody alokacji, np. stosowanie wskaźników, dynamicznych tablic lub struktur danych takich jak lista czy mapa, pozwala na budowanie bardziej skalowalnych i elastycznych aplikacji.

Pytanie 13

Jakie rezultaty pojawią się po uruchomieniu poniższego kodu napisanego w języku C++?

class KlasaBazowa {
    public:
        virtual void metoda() {
            cout << "Bazowa. ";
        }
};

class KlasaPochodna : public KlasaBazowa {
    public:
        void metoda() {
            cout << "Pochodna. ";
        }
};

int main() {
    KlasaBazowa *bazowa = new KlasaPochodna();
    KlasaPochodna *pochodna = new KlasaPochodna();

    bazowa->metoda();
    pochodna->metoda();
    return 0;
}
A. Pochodna. Bazowa.
B. Bazowa. Bazowa.
C. Pochodna. Pochodna.
D. Bazowa. Pochodna.
Wyświetlenie 'Bazowa. Pochodna.' wskazywałoby, że tylko jedna z metod została nadpisana, co nie ma sensu w tym przypadku. Znacznik 'Bazowa. Bazowa.' to już totalny brak polimorfizmu, co zupełnie mija się z celem tego kodu. A 'Pochodna. Bazowa.' sugerowałoby, że mamy do czynienia z częściowym nadpisaniem metod, co też nie jest zgodne z tym, co mamy w kodzie.

Pytanie 14

Jakie znaczenie ma pojęcie "debugowanie" w kontekście programowania?

A. Przygotowywanie dokumentacji kodu
B. Wdrażanie aplikacji w środowisku produkcyjnym
C. Wyszukiwanie i usuwanie błędów w kodzie
D. Tworzenie nowych funkcjonalności aplikacji
Debugowanie to proces wyszukiwania i eliminowania błędów (bugów) w kodzie źródłowym programu. Polega na analizowaniu działania aplikacji linia po linii, śledzeniu wartości zmiennych, analizie stosu wywołań i wykrywaniu miejsc, w których program działa niezgodnie z oczekiwaniami. Debugowanie umożliwia programistom szybkie odnajdywanie błędów logicznych, składniowych oraz problemów z wydajnością aplikacji. Narzędzia takie jak Visual Studio, PyCharm, IntelliJ IDEA czy Chrome DevTools oferują zaawansowane funkcje debugowania, takie jak punkty przerwań (breakpoints), krokowe wykonywanie kodu i podgląd pamięci. Proces debugowania jest kluczowy w każdym etapie rozwoju oprogramowania, ponieważ znacząco wpływa na stabilność i jakość finalnego produktu.

Pytanie 15

Który z wymienionych typów testów najlepiej ocenia odporność aplikacji na intensywne obciążenie?

A. Testy bezpieczeństwa
B. Testy zgodności
C. Testy obciążeniowe
D. Testy funkcjonalne
Testy obciążeniowe to rodzaj testów, które sprawdzają, jak aplikacja radzi sobie z dużym ruchem użytkowników lub przetwarzaniem dużych ilości danych. Celem testów obciążeniowych jest wykrycie potencjalnych wąskich gardeł, identyfikacja problemów z wydajnością oraz określenie maksymalnej przepustowości aplikacji. Testy te są kluczowe dla aplikacji o wysokim natężeniu ruchu, takich jak sklepy internetowe czy systemy bankowe, gdzie stabilność pod obciążeniem jest krytyczna dla sukcesu.

Pytanie 16

Przedstawione w filmie działania wykorzystują narzędzie

A. kompilatora dla interfejsu graficznego
B. generatora kodu java
C. generatora GUI przekształcającego kod do języka XAML
D. debuggera analizującego wykonujący kod
Patrząc na wszystkie dostępne opcje, łatwo się pomylić, bo terminologia może być trochę podchwytliwa. Debugger analizujący wykonujący kod rzeczywiście jest kluczowym narzędziem w pracy programisty, ale jego zadaniem jest szukanie błędów i obserwowanie działania programu w czasie rzeczywistym, a nie generowanie kodu czy interfejsów. Myślę, że sporo osób utożsamia narzędzia developerskie z debuggerem, bo to jedno z najczęściej używanych rozwiązań – jednak tutaj akurat nie ma on nic wspólnego z przekształcaniem kodu do XAML-a. Generator kodu Java brzmi sensownie, jeśli ktoś pracuje więcej w środowiskach Javy, ale w tym przypadku mówimy o ekosystemie .NET i XAML-u, a Java ma zupełnie inne formaty i narzędzia (np. FXML dla JavaFX, ale to zupełnie inna bajka). Generator GUI przekształcający kod do języka XAML to narzędzie dedykowane platformie Microsoftu, bo XAML funkcjonuje właśnie w tych technologiach. Ostatnia odpowiedź, czyli kompilator dla interfejsu graficznego, to trochę pomieszanie pojęć – kompilator rzeczywiście tłumaczy kod na wykonywalny plik (np. EXE), ale nie jest narzędziem służącym do generowania czy przekształcania opisów interfejsów graficznych. Sporo osób może mieć tendencję do mylenia generatorów z kompilatorami, bo oba „tworzą coś automatycznie”, ale ich przeznaczenie jest zupełnie inne. Moim zdaniem najważniejsze to rozumieć, że generatory GUI ułatwiają życie, pozwalając szybko przenieść projekt interfejsu do kodu XAML, a reszta narzędzi ma zupełnie inne zadania. To rozróżnienie jest naprawdę kluczowe w branży.

Pytanie 17

Jakie zadanie wykonuje debugger?

A. Identyfikowanie błędów składniowych podczas kompilacji
B. Przekładanie kodu źródłowego na język maszynowy
C. Umożliwianie analizy działania programu krok po kroku
D. Generowanie pliku wykonywalnego programu
Debugger umożliwia analizę działania programu krok po kroku, co jest kluczowe dla wykrywania i usuwania błędów logicznych oraz programistycznych. Debugowanie pozwala na śledzenie wartości zmiennych w czasie rzeczywistym, analizowanie przepływu programu i zatrzymywanie go w określonych punktach (breakpoints). Dzięki temu programista może znaleźć i naprawić błędy przed finalnym wdrożeniem aplikacji. Debuggery są nieodłącznym elementem środowisk IDE (Integrated Development Environment), takich jak Visual Studio, PyCharm czy Eclipse, i stanowią fundamentalne narzędzie w procesie programowania.

Pytanie 18

Które z wymienionych narzędzi nie znajduje zastosowania w tworzeniu aplikacji desktopowych?

A. Edytor graficzny
B. Debugger
C. Przeglądarka internetowa
D. Kompilator
Przeglądarka internetowa nie jest narzędziem wykorzystywanym bezpośrednio w procesie tworzenia aplikacji desktopowych. Chociaż może służyć do przeszukiwania dokumentacji lub testowania aplikacji webowych, jej funkcjonalność nie wspiera bezpośredniego tworzenia aplikacji desktopowych. W tworzeniu aplikacji desktopowych kluczowe są narzędzia takie jak kompilatory, debugery i edytory kodu. Kompilatory przekształcają kod źródłowy na kod wykonywalny, debugery pozwalają na śledzenie błędów, a edytory kodu umożliwiają pisanie i edytowanie aplikacji.

Pytanie 19

Co oznacza pojęcie TDD w kontekście programowania?

A. Technical Design Document - dokumentacja techniczna projektu
B. Task Deployment Diagram - schemat wdrażania zadań w projekcie
C. Test-Driven Development - praktyka pisania testów przed implementacją kodu
D. Type Definition Document - dokumentacja typów danych w aplikacji
Test-Driven Development (TDD) to metodologia programowania, w której proces tworzenia kodu zaczyna się od pisania testów. TDD polega na cyklicznym podejściu do rozwoju oprogramowania, w którym najpierw definiujemy, jakie funkcjonalności będzie miał nasz kod, a następnie implementujemy tylko te elementy, które są niezbędne do przejścia wcześniej napisanych testów. Dzięki temu, deweloperzy mają możliwość natychmiastowego sprawdzenia poprawności swojego kodu, co sprzyja eliminacji błędów na wczesnym etapie. Przykład zastosowania TDD można zobaczyć w tworzeniu aplikacji webowych, gdzie programista pisze testy jednostkowe dla nowych funkcji, a następnie implementuje te funkcje, poprawiając kod tylko w przypadku, gdy testy nie przechodzą. Takie podejście pozwala na zwiększenie jakości oprogramowania oraz jego łatwiejszą refaktoryzację. Warto również zauważyć, że TDD jest zgodne z praktykami Agile i Continuous Integration, co pozwala na efektywniejsze zarządzanie projektem i dostosowywanie go do wymagań zmieniającego się rynku.

Pytanie 20

Które narzędzie najlepiej nadaje się do analizy wydajności aplikacji JavaScript?

A. npm
B. Webpack
C. Babel
D. Chrome DevTools Performance
Chrome DevTools Performance to potężne narzędzie, które jest integralną częścią przeglądarki Google Chrome i służy do analizy wydajności aplikacji JavaScript. Dzięki niemu możemy monitorować czas ładowania, identyfikować wąskie gardła w kodzie oraz analizować, jak różne elementy strony wpływają na ogólną wydajność. Narzędzie to umożliwia nagrywanie sesji wydajności, co pozwala na szczegółowe zbadanie, jak różne operacje wpływają na czas odpowiedzi aplikacji. Przykładowo, możemy użyć DevTools do analizy, które skrypty zajmują najwięcej czasu lub które zadania blokują wątek główny, co jest kluczowe dla zapewnienia płynności interfejsu użytkownika. Dodatkowo, narzędzie to oferuje różne metryki, takie jak FPS (frames per second), co jest niezbędne do oceny płynności animacji. Warto również podkreślić, że DevTools jest zgodne z najlepszymi praktykami branżowymi, a jego umiejętne wykorzystanie może znacząco poprawić jakość aplikacji.

Pytanie 21

Jakie narzędzie umożliwia testowanie API w aplikacjach internetowych?

A. Blender
B. Postman
C. Node.js
D. Microsoft Excel
Postman to jedno z najczęściej wykorzystywanych narzędzi do testowania API aplikacji webowych. Umożliwia wysyłanie żądań HTTP, testowanie endpointów oraz monitorowanie odpowiedzi serwera. Dzięki Postmanowi programiści mogą w łatwy sposób analizować dane przesyłane między frontendem a backendem, co jest kluczowe w trakcie budowania nowoczesnych aplikacji opartych na architekturze REST lub GraphQL. Narzędzie oferuje możliwość automatyzacji testów, co przyspiesza proces wykrywania błędów i zwiększa jakość dostarczanych aplikacji. Postman pozwala także na tworzenie skryptów pre-request i testowych, umożliwiając weryfikację poprawności danych oraz sprawdzanie integralności aplikacji na różnych etapach jej rozwoju.

Pytanie 22

Które z poniższych nie jest frameworkiem do testowania w JavaScript?

A. Mocha
B. Jasmine
C. Jest
D. Express
Express jest popularnym frameworkiem do budowania aplikacji webowych na platformie Node.js, a nie narzędziem do testowania. Jego głównym celem jest ułatwienie tworzenia serwerów HTTP oraz zarządzanie routingiem i middleware w aplikacjach. W praktyce, Express pozwala na szybkie i efektywne tworzenie API, co jest kluczowe w nowoczesnym rozwoju aplikacji. W kontekście testowania aplikacji, mogą być stosowane inne frameworki, takie jak Mocha, Jest czy Jasmine, które oferują funkcjonalności dedykowane do pisania i uruchamiania testów. Dobrą praktyką jest oddzielanie logiki testowej od logiki aplikacji, co osiąga się przy użyciu odpowiednich narzędzi, takich jak wspomniane frameworki testowe. Zrozumienie różnicy między serwerowymi frameworkami, jak Express, a frameworkami do testowania, jest istotne dla każdego programisty, aby efektywnie dobierać narzędzia do pracy.

Pytanie 23

Wskaż rodzaj testów, które przeprowadza się podczas fazy tworzenia kodu źródłowego

A. testy wdrożeniowe
B. testy kompatybilności
C. testy jednostkowe
D. testy wydajnościowe
Testy jednostkowe to, moim zdaniem, absolutny fundament solidnego programowania. Są to niewielkie, automatyczne testy, które programista pisze zwykle równolegle z kodem albo nawet przed nim, jeśli stosuje się TDD (Test-Driven Development). Chodzi o to, żeby każda najmniejsza część programu – funkcja, metoda czy klasa – była dokładnie sprawdzona, czy zachowuje się zgodnie z założeniami już na etapie pisania kodu. W praktyce wygląda to tak: piszesz sobie funkcję, która np. liczy VAT, i od razu piszesz kilka testów, które sprawdzają, czy dla różnych wartości zwraca ona poprawne wyniki. Gdy coś się zmieni w kodzie, testy jednostkowe pozwalają od razu wychwycić, że coś zepsułeś (albo, oby nie, ktoś inny). Standardy branżowe, jak np. ISTQB czy wytyczne IEEE 829, bardzo mocno podkreślają wagę testów jednostkowych – bez nich zarządzanie jakością oprogramowania jest po prostu niemożliwe na dłuższą metę. W praktyce nawet proste projekty szybko bez nich zamieniają się w chaos. Co ciekawe, dobrze napisane testy jednostkowe ułatwiają refaktoryzację, bo masz pewność, że po zmianach wszystko działa jak należy. W mojej opinii, jeśli ktoś naprawdę poważnie myśli o pracy w branży IT, powinien umieć pisać testy jednostkowe z marszu.

Pytanie 24

Co zostanie wyświetlone po wykonaniu poniższego kodu w PHP?

$x = 5;
$y = '5';
var_dump($x == $y);
var_dump($x === $y);
A. bool(false) bool(false)
B. bool(true) bool(true)
C. bool(true) bool(false)
D. bool(false) bool(true)
Wyniki bool(false) bool(false), bool(true) bool(true) oraz bool(false) bool(true) mogą wydawać się zrozumiałe na pierwszy rzut oka, jednak każdy z tych przypadków zawiera istotne błędy w zrozumieniu mechanizmu porównania w PHP. Porównanie z użyciem operatora ==, który jest porównaniem luźnym, prowadzi do konwersji typów, co nie jest zawsze intuicyjne. Użytkownicy mogą mylnie przyjąć, że porównania opierające się na tym operatorze zawsze zwracają false, gdy zmienne mają różne typy, co jest błędne. W rzeczywistości, w przypadku wyrażenia $x == $y, gdzie $x to integer a $y to string, PHP przekształca zmienną stringową na typ integer przed porównaniem, co skutkuje wynikiem true. W konsekwencji, błędne odpowiedzi mogłyby wynikać z niepełnego zrozumienia działania operatora ===, który wymaga, by zarówno wartość, jak i typ były identyczne. Użytkownicy mogą mylić te dwa operatory i zakładać, że wynik będzie taki sam, niezależnie od typów zmiennych. Warto również zwrócić uwagę na to, jak ważne jest stosowanie operatora identyczności ===, który nie tylko porównuje wartości, ale także typy, co jest zgodne z dobrymi praktykami programowania w PHP. Dzięki temu unika się niejednoznaczności, co jest istotne w skomplikowanych aplikacjach. Wnioskując, kluczem do poprawnych wyników jest znajomość różnicy między porównaniami luźnymi a ścisłymi i świadome używanie odpowiednich operatorów, by unikać nieporozumień.

Pytanie 25

Jakie są różnice między testami funkcjonalnymi a niefunkcjonalnymi?

A. Testy funkcjonalne koncentrują się na interfejsie, a niefunkcjonalne na backendzie aplikacji
B. Testy funkcjonalne są realizowane tylko przez końcowych użytkowników, natomiast niefunkcjonalne przez programistów
C. Testy funkcjonalne oceniają zgodność działania aplikacji z założeniami, a niefunkcjonalne analizują aspekty wydajności, bezpieczeństwa i użyteczności
D. Testy funkcjonalne oceniają wydajność aplikacji, podczas gdy niefunkcjonalne weryfikują poprawność kodu
Testy funkcjonalne sprawdzają, czy aplikacja działa zgodnie z założeniami i spełnia określone wymagania użytkownika. Obejmują one testowanie interfejsu, przepływu pracy oraz funkcji kluczowych dla działania oprogramowania. Testy niefunkcjonalne koncentrują się na aspektach takich jak wydajność, skalowalność, bezpieczeństwo i użyteczność. Różnica polega na tym, że testy funkcjonalne oceniają 'co' robi aplikacja, podczas gdy testy niefunkcjonalne oceniają 'jak dobrze' aplikacja działa w różnych warunkach. Testy niefunkcjonalne obejmują testy obciążeniowe (load testing), testy penetracyjne oraz analizy UX. Oba typy testów są niezbędne dla zapewnienia wysokiej jakości oprogramowania i jego niezawodności w środowisku produkcyjnym.

Pytanie 26

Jaką rolę pełni instrukcja throw w języku C++?

A. Zgłasza wyjątek, który można przechwycić za pomocą bloku catch
B. Przerywa działanie programu, gdy wystąpi wyjątek
C. Inicjuje nowy wyjątek podczas działania aplikacji
D. Ogranicza zasięg zmiennych w bloku try
Instrukcja 'throw' w C++ służy do zgłaszania wyjątków, które mogą być następnie przechwycone i obsłużone przez blok 'catch'. Mechanizm ten pozwala na przerwanie normalnego przepływu programu w przypadku wystąpienia błędu i skierowanie sterowania do odpowiedniego miejsca obsługi wyjątków. 'Throw' jest kluczowym elementem obsługi błędów i umożliwia propagowanie informacji o błędach na wyższe poziomy programu, co pozwala na ich efektywną obsługę. Używanie wyjątków poprawia czytelność kodu, umożliwiając oddzielenie logiki biznesowej od logiki obsługi błędów.

Pytanie 27

W języku C++, zakładając, że przedstawiony fragment kodu poprawnie się skompiluje i zostanie wykonany, to zmiennej liczba przypisana zostanie wartość:

int liczba = rand() % 1000;
A. pseudolosowa nie większa niż 999
B. równa 1000
C. rzeczywista podzielna przez 1000
D. dowolna pseudolosowa z przedziału typu int
Błędne odpowiedzi wynikają z niezrozumienia mechaniki działania funkcji rand() i operatora modulo w języku C++. Pierwsza koncepcja, że liczba mogłaby być równa 1000, jest błędna, ponieważ operator modulo ogranicza wynik do wartości mniejszych niż dzielnik, w tym przypadku 1000. Dlatego wynik nigdy nie osiągnie wartości 1000. Drugą błędną koncepcją jest przypisanie dowolnej liczby pseudolosowej w zakresie typu int. Funkcja rand() bez operacji modulo generuje liczby w zakresie od 0 do RAND_MAX, ale zastosowanie modulo 1000 zawęża ten zakres do wartości od 0 do 999. Trzecia koncepcja, że wynik musi być liczbą rzeczywistą podzielną przez 1000, wynika z błędnego założenia o typie danych i działaniach matematycznych. W kontekście języka C++ kod operuje na liczbach całkowitych, a nie rzeczywistych, i wynik modulo nie może być podzielny przez 1000, gdyż wartości te nigdy nie osiągną 1000. Kluczowe jest zrozumienie, że operacja modulo ogranicza zakres wyników i zapobiega wyjściu poza określoną wartość maksymalną, co jest fundamentalnym aspektem generowania liczb pseudolosowych w kontrolowanych zakresach. Dzięki temu podejściu można bezpiecznie i efektywnie wykorzystywać generowane wyniki w wielu zastosowaniach informatycznych, unikając typowych błędów logicznych i zakresowych w programowaniu.

Pytanie 28

Jakie będą skutki wykonania podanego fragmentu kodu w języku C++?

vector <int> liczby;
for(int i=0; i<10; i++) {
    liczby.push_back(2*i);
}
A. Do tablicy liczby, na jej początku, dodawane są nowe wartości.
B. Z tablicy liczby usuwane są elementy, z każdym obiegiem pętli eliminowany jest element z jej końca.
C. Z tablicy liczby usuwane są elementy, z każdym obiegiem pętli eliminowany jest element z jej początku.
D. Do tablicy liczby, na jej końcu, dodawane są nowe wartości.
Kod, który został przedstawiony, pokazuje bardzo typowe zastosowanie kontenera std::vector w C++. Metoda push_back() dodaje nowy element zawsze na końcu wektora, co oznacza, że kolejne wywołania tej funkcji będą rozszerzać tablicę o nowe wartości w porządku dodawania. W tym konkretnym przykładzie do pustego wektora liczby, w każdej iteracji pętli for dodawana jest liczba będąca podwojeniem indeksu – czyli 0, 2, 4, 6, 8, aż do 18 włącznie (bo i przyjmuje wartości od 0 do 9). To bardzo przyjazny i intuicyjny sposób na dynamiczne rozbudowywanie zbioru danych bez konieczności martwienia się o ręczne zarządzanie rozmiarem tablicy, co w języku C++ jest częstym źródłem błędów w przypadku zwykłych tablic. Z mojego doświadczenia korzystanie z push_back() jest czymś absolutnie podstawowym w codziennej pracy programisty, zwłaszcza jeśli chodzi o szybkie prototypowanie czy operacje na listach wynikowych. Warto zwrócić uwagę, że vector zapewnia też wydajne zarządzanie pamięcią - automatycznie rezerwuje przestrzeń, a w razie potrzeby powiększa ją. Standard C++ promuje stosowanie kontenerów STL właśnie z uwagi na bezpieczeństwo i wygodę użytkowania, więc to rozwiązanie jest nie tylko poprawne, ale też zgodne z dobrymi praktykami. Często w praktyce spotyka się właśnie takie sekwencyjne dodawanie elementów do końca wektora, chociażby przy wczytywaniu danych z plików czy budowaniu dynamicznych struktur.

Pytanie 29

Jakie elementy powinny być uwzględnione w scenariuszu testów aplikacji?

A. Strategia wdrożenia aplikacji w środowisku produkcyjnym
B. Dokładne wytyczne dotyczące realizacji kodu
C. Zestaw kroków do testowania, oczekiwanych rezultatów oraz warunków początkowych
D. Dokumentacja techniczna oprogramowania
Scenariusz testowy aplikacji powinien zawierać szczegółowy opis kroków testowych, oczekiwane wyniki oraz warunki wstępne, które muszą być spełnione przed rozpoczęciem testu. Scenariusz testowy to kluczowy dokument w procesie testowania oprogramowania, który pozwala na systematyczne i dokładne sprawdzenie, czy aplikacja działa zgodnie z oczekiwaniami. Uwzględnienie kroków testowych pozwala na replikację testów, a opis warunków wstępnych zapewnia, że test jest przeprowadzany w odpowiednim środowisku.

Pytanie 30

Dlaczego w wyniku działania tego kodu w języku C++ na ekranie pojawiła się wartość 0 zamiast 50?

int oblicz(int x)  {
    int i = 50;
    x = x + i;
    return i;
}

int main()  {
    int x = 0;
    int wynik = oblicz(x);
    std::cout << x;
}
A. Funkcja zwraca wartość, chociaż nie powinna jej zwracać.
B. Zmienna x powinna być inicjowana wartością równą 1, a nie 0.
C. Niepoprawnie zdefiniowano działanie wewnątrz funkcji.
D. Argument funkcji został przekazany przez wartość, a nie przez referencję.
W C++ funkcje standardowo dostają argumenty przez wartość, co znaczy, że dostają kopię tego, co do nich wysyłamy. W tym kodzie, jak widzisz, zmienna x idzie do funkcji oblicz jako kopia. To sprawia, że jakiekolwiek zmiany w x w tej funkcji nie mają wpływu na x w funkcji main. Dlatego po wywołaniu oblicz(x) wartość x w main zostaje taka sama. Jeśli chcesz, żeby zmiany wewnątrz funkcji były widoczne w funkcji, która ją wywołuje, to musisz użyć przekazywania przez referencję. Robisz to, dodając & w deklaracji parametru funkcji, czyli robisz to tak: void oblicz(int &x). Przekazywanie przez referencję to dobra praktyka, gdy chcesz, aby funkcja mogła zmieniać wartość argumentu. A dodatkowo jest to efektywniejsze, bo unikasz kopiowania danych, co bywa kosztowne, szczególnie przy dużych strukturach danych.

Pytanie 31

Jaki będzie wynik działania poniższego kodu w języku Python?

def fun(x, l=[]):
    l.append(x)
    return l

print(fun(1))
print(fun(2))
print(fun(3, []))
print(fun(4))
A. [1], [2], [3], [4, 3]
B. [1], [2], [3], [4]
C. [1], [1, 2], [3], [1, 2, 4]
D. [1], [1, 2], [3], [3, 4]
Wynik działania tego kodu jest poprawny i wynika z zrozumienia, jak Python obsługuje domyślne argumenty funkcji. W momencie, gdy funkcja 'fun' jest wywoływana po raz pierwszy z argumentem 1, lista 'l' jest pusta i dodawany jest do niej element 1, co skutkuje wynikiem [1]. Przy kolejnym wywołaniu z argumentem 2, lista 'l' nie jest tworzona na nowo, a zamiast tego używane jest to samo odniesienie do istniejącej listy, co oznacza, że 2 zostaje dodane do listy, przekształcając ją w [1, 2]. W trzecim wywołaniu funkcji, przekazujemy nową, pustą listę, więc wynik to [3]. Kiedy po raz czwarty wywołujemy funkcję z argumentem 4, znowu używamy tej samej listy, do której dodano już 1 i 2, co daje nam wynik [1, 2, 4]. Kluczowe jest zrozumienie, że domyślne argumenty w Pythonie są tworzone raz, więc nie są resetowane przy kolejnych wywołaniach funkcji. Takie zarządzanie pamięcią w Pythonie jest zgodne z dobrymi praktykami programistycznymi oraz pozwala na efektywne użycie zasobów.

Pytanie 32

Jakie kroki należy podjąć po wykryciu błędu w kodzie podczas testowania?

A. Pominąć błąd, jeżeli aplikacja funkcjonuje poprawnie
B. Zgłosić błąd użytkownikowi końcowemu
C. Usunąć moduł, który zawiera błąd
D. Naprawić błąd i przeprowadzić ponowne testy aplikacji
Po znalezieniu błędu w kodzie podczas testowania kluczowym krokiem jest poprawienie błędu i ponowne przetestowanie aplikacji. Taki cykl iteracyjny pozwala na eliminację błędów i zapewnienie, że aplikacja działa zgodnie z oczekiwaniami. Testowanie po każdej poprawce jest niezbędne, aby upewnić się, że wprowadzone zmiany nie wpłynęły negatywnie na inne części aplikacji. Taka praktyka jest integralną częścią Continuous Integration (CI) i Continuous Deployment (CD), które zakładają częste wdrażanie i testowanie kodu. Poprawienie błędów na wczesnym etapie rozwoju minimalizuje koszty i czas potrzebny na naprawę błędów w fazie produkcyjnej, co przyczynia się do stabilności i wysokiej jakości końcowego produktu.

Pytanie 33

Wynikiem wykonania poniższego fragmentu kodu jest wyświetlenie liczb z zakresu od 2 do 20, które są

for (let number = 2; number <= 20; number++) {
    let check = true;
    for (let test = 2; test < number; test++) {
        if (number % test === 0) {
            check = false;
            break;
        }
    }
    if (check) console.log(number);
}
A. pierwsze.
B. podzielne przez wartość zmiennej test.
C. podzielne przez wartość zmiennej check.
D. parzyste.
Kod wypisuje liczby pierwsze, czyli takie, które mają dokładnie dwa dzielniki: 1 i samą siebie. Liczby pierwsze są podstawą w wielu dziedzinach matematyki i informatyki, szczególnie w kryptografii i algorytmach. Wyszukiwanie liczb pierwszych w danym przedziale to popularne zadanie, które pozwala na lepsze zrozumienie iteracji, pętli i warunków logicznych w programowaniu. Algorytm ten jest również wykorzystywany w optymalizacji algorytmów szyfrowania i generowania kluczy.

Pytanie 34

Jak nazywa się proces znajdowania i usuwania błędów w kodzie?

A. Kompilowanie
B. Debugowanie
C. Kompensowanie
D. Interpretowanie
Debugowanie to niezwykle istotny etap w procesie tworzenia oprogramowania, polegający na identyfikowaniu i eliminowaniu błędów w kodzie źródłowym. Jest to proces, który wymaga zrozumienia logiki programu oraz umiejętności analitycznych, aby skutecznie odnaleźć przyczynę problemu i ją usunąć. Debugowanie jest kluczowe dla zapewnienia, że aplikacja działa zgodnie z zamierzeniami i jest wolna od błędów, które mogłyby wpłynąć na jej funkcjonalność lub stabilność. W praktyce debugowanie może obejmować różne techniki, takie jak użycie narzędzi do śledzenia wykonania kodu, analizę logów czy testowanie jednostkowe. Programiści często korzystają z dedykowanych środowisk programistycznych (IDE), które oferują funkcje ułatwiające debugowanie, takie jak punkty przerwań czy inspekcja zmiennych. Dobrym przykładem jest Visual Studio, które umożliwia śledzenie wartości zmiennych w czasie rzeczywistym. Debugowanie jest również częścią dobrych praktyk programistycznych, które zakładają regularne testowanie i kontrolę jakości kodu. Dzięki temu możliwe jest nie tylko eliminowanie błędów, ale także poprawa wydajności i bezpieczeństwa aplikacji.

Pytanie 35

Co następuje, gdy błąd nie zostanie uchwycony przez blok catch?

A. Program kontynuuje działanie, pomijając błąd
B. Program zakończy działanie z błędem
C. Instrukcja throw zostanie automatycznie wykreślona
D. Błąd zostanie zignorowany przez kompilator
Jeśli wyjątek nie zostanie przechwycony przez blok 'catch', program zakończy działanie z błędem i wygeneruje komunikat o nieobsłużonym wyjątku. Jest to domyślne zachowanie w C++ i innych językach obsługujących wyjątki, co ma na celu zapobieganie dalszemu wykonywaniu kodu, który mógłby prowadzić do nieprzewidywalnych rezultatów. Obsługa wyjątków jest kluczowym elementem zapewniania stabilności i bezpieczeństwa aplikacji – brak jej implementacji może prowadzić do awarii programu. Dlatego zaleca się, aby zawsze stosować odpowiednie bloki 'try-catch' wokół kodu, który może generować wyjątki.

Pytanie 36

W przedstawionych funkcjonalnie równoważnych kodach źródłowych po przeprowadzeniu operacji w zmiennej b zostanie zapisany wynik:

Python:C++/C#/Java:
x = 5.96;
b = int(x);
double x = 5.96;
int b = (int)x;
A. 5.96
B. 5
C. 596
D. 6
Odpowiedź 5 jest prawidłowa, bo w większości popularnych języków programowania, takich jak Python, C++, C#, czy Java, rzutowanie liczby zmiennoprzecinkowej (czyli typu float lub double) na typ całkowity (int) powoduje odcięcie części ułamkowej, a nie zaokrąglenie. To jest bardzo ważne, bo wiele osób intuicyjnie spodziewa się zaokrąglenia, a tu po prostu wszystko po przecinku ląduje w koszu. W przypadku podanego przykładu zmienna x ma wartość 5.96, ale po rzutowaniu na int, zarówno w Pythonie poprzez funkcję int(), jak i w pozostałych językach przez klasyczne rzutowanie (int)x, zostaje tylko 5. Dokładnie tak działa konwersja: odcina się część po przecinku niezależnie od tego, jak blisko liczba jest kolejnej całości. To niesamowicie przydatne np. podczas pracy z indeksami tablic albo gdy chcemy szybko zamienić wynik dzielenia na liczbę całkowitą. W praktyce, warto pamiętać, że takie rzutowanie nie wykonuje żadnej walidacji ani sprawdzania – jeśli liczba jest ujemna, to po prostu też odcina część ułamkową w kierunku zera, więc int(-5.96) da -5. Z mojego doświadczenia bardzo często spotyka się błąd w kodzie, kiedy ktoś oczekuje zaokrąglenia i nie otrzymuje go, bo rzutowanie zawsze odcina, nie zaokrągla. Warto znać tę różnicę przy projektowaniu algorytmów i korzystać np. z funkcji round() jeśli potrzebujemy zaokrąglenia, a nie odcinania. To takie małe niuanse, ale potem wchodzą w nawyk i bardzo ułatwiają życie podczas kodowania.

Pytanie 37

W klasie pracownik zdefiniowano następujące metody:

pracownik()   { ... }
static void wypisz()   { ... }
int operator== (const pracownik &prac) { ... }
~pracownik()   { ... }
Która z nich jest odpowiednia do dodania elementu diagnostycznego o treści:
cout << "Obiekt został usunięty";
Ilustracja do pytania
A. operator==
B. pracownik
C. wypisz
D. ~pracownik
Destruktor to specjalna metoda w języku C++ oznaczona tyldą przed nazwą klasy która jest wywoływana automatycznie w momencie usuwania obiektu danego typu z pamięci. Dlatego dodanie elementu diagnostycznego cout<<Obiekt został usunięty; jest najbardziej sensowne w destruktorze ponieważ pozwala na śledzenie momentu w którym obiekt przestaje istnieć. Takie podejście jest zgodne z dobrymi praktykami programistycznymi ponieważ pomaga w debugowaniu i zarządzaniu zasobami w programie. Warto zauważyć że destruktory są kluczowe w kontekście zarządzania pamięcią szczególnie gdy klasa dynamicznie alokuje zasoby. Wówczas destruktor powinien zawierać kod zwalniający te zasoby aby uniknąć wycieków pamięci. Dodawanie diagnostycznych komunikatów może pomóc programistom w identyfikacji potencjalnych błędów związanych z zarządzaniem cyklem życia obiektów i poprawić ogólną stabilność i czytelność kodu. Praktyka ta jest szczególnie ważna w dużych projektach gdzie ręczne śledzenie wszystkich obiektów byłoby trudne i czasochłonne. Warto stosować taką diagnostykę w połączeniu z nowoczesnymi narzędziami do profilowania i analizy pamięci co zwiększa efektywność procesu programistycznego.

Pytanie 38

Co to jest automatyzacja testowania procesów?

A. Integracją testów w środowisku deweloperskim
B. Używaniem narzędzi oraz skryptów do wykonywania testów w sposób automatyczny bez udziału człowieka
C. Sprawdzaniem poprawności działania aplikacji na urządzeniach przenośnych
D. Kompilowaniem kodu w celu zwiększenia efektywności
Automatyzacja procesu testowania to zastosowanie narzędzi, skryptów i technologii do przeprowadzania testów oprogramowania w sposób zautomatyzowany, bez konieczności ciągłej ingerencji człowieka. Automatyzacja pozwala na szybkie i wielokrotne uruchamianie testów regresyjnych, co znacząco zwiększa efektywność testowania, redukuje czas potrzebny na wykrycie błędów i umożliwia jednoczesne testowanie wielu funkcji. Narzędzia takie jak Selenium, JUnit czy TestNG pozwalają na tworzenie skryptów testowych, które automatycznie weryfikują poprawność działania aplikacji na różnych urządzeniach i w różnych środowiskach. Automatyzacja testów to nie tylko oszczędność czasu, ale także wyższa dokładność i powtarzalność testów, co minimalizuje ryzyko przeoczenia krytycznych błędów.

Pytanie 39

Po wykonaniu poniższego kodu na konsoli zostanie wyświetlona liczba:

int a = 0x73;
cout << a;
A. 115
B. 73
C. 0
D. 108
Wartość 0x73 w kodzie oznacza liczbę zapisaną w systemie szesnastkowym (heksadecymalnym). To bardzo często wykorzystywana notacja w programowaniu, szczególnie gdy pracuje się z pamięcią, kodowaniem kolorów lub niskopoziomową obsługą sprzętu. 0x73 to po prostu 7 * 16 + 3, co daje 115 w systemie dziesiętnym. Gdy taki zapis przekażesz do cout, kompilator automatycznie prezentuje tę wartość jako liczbę w systemie dziesiętnym, czyli właśnie 115. Szczerze mówiąc, moim zdaniem warto jak najczęściej ćwiczyć odczytywanie i zamianę wartości pomiędzy systemami liczbowymi, bo to się naprawdę przydaje przy analizie kodu, debugowaniu czy choćby rozumieniu dokumentacji technicznej. Taka umiejętność jest praktycznie niezbędna w embedded, ale i w zwykłym C++ można czasem natknąć się na takie zapisy – szczególnie w kodzie legacy. Osobiście uważam, że dobrze od razu rozpoznawać takie zapisy i nie tracić czasu na kalkulatory. Warto też pamiętać, że podobnie działają inne systemy: np. 0b1101 to binarny, a 0x to zawsze heksadecymalny. W standardzie C++ zapis z prefiksem 0x jest w pełni poprawny i zalecany przy pracy z wartościami bitowymi. Fajnie, jak ktoś łapie takie rzeczy od razu, bo później w pracy nad większymi projektami to ogromne ułatwienie.

Pytanie 40

Co oznacza walidacja kodu programu?

A. Czynnością związaną z tworzeniem dokumentacji kodu
B. Czynnością weryfikującą poprawność i zgodność kodu z założeniami
C. Czynnością polegającą na kompilowaniu kodu
D. Czynnością dotyczącą publikacji aplikacji w sklepie
Walidacja kodu programu to proces sprawdzania jego poprawności i zgodności z założeniami projektowymi oraz standardami programistycznymi. Celem walidacji jest wykrycie błędów logicznych, składniowych i zgodności kodu z wymaganiami aplikacji. Walidacja może obejmować analizę statyczną kodu (bez jego wykonywania) oraz testy jednostkowe i integracyjne, które sprawdzają funkcjonalność aplikacji. Dzięki walidacji programiści mogą uniknąć błędów na późniejszych etapach rozwoju projektu, co znacząco zwiększa niezawodność i stabilność aplikacji. Proces ten jest nieodzowny w metodykach Agile i Continuous Integration, gdzie regularne testowanie kodu stanowi podstawę dostarczania wysokiej jakości oprogramowania.