Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Tomasz Gądek

Tomasz Gądek | Strona domowa

O mnie

Jestem programistą, twórcą kursów IT/AI oraz wykładowcą akademickim. Prowadzę zajęcia z języków znacznikowych, narzędzi i środowisk programistycznych oraz testowania i jakości oprogramowania. Na tej stronie znajdziesz materiały, które pomogą Ci rozwijać umiejętności w tych obszarach.

Materiały dydaktyczne

Konsultacje i kontakt

Jeśli masz pytania lub potrzebujesz wyjaśnień, zapraszam na konsultacje (stacjonarnie lub zdalnie) Proszę o wcześniejsze ustalenie terminu drogą mailową.

Kontakt: t_gadek@atar.edu.pl

Przesyłanie zadań

Rozwiązania zadań można przesłać przez formularz.

Narzędzia i środowiska programistyczne

Kurs obejmuje podstawy programowania, pracę z Gitem i GitHub, organizację pracy zespołowej, code review oraz dokumentację projektu.

Narzędzia i środowiska programistyczne

Przedmiot obejmuje praktyczne ćwiczenia z podstaw programowania, pracy z Gitem i GitHub, organizacji zespołu, przeglądu kodu oraz dokumentacji projektu. W trakcie zajęć studenci uczą się rozwiązywania problemów, pracy w środowisku programistycznym i korzystania z najważniejszych narzędzi wspierających pracę zespołową.

Poniżej lista ćwiczeń dostępnych jako pliki PDF.

NrTematPDF
L#01Podstawy programowania w języku Kotlinnisp-lab01.pdf
L#02Instrukcje warunkowe oraz pętlenisp-lab02.pdf
L#03Tablice, funkcje, zakresy, łańcuchy znaków, debugowanie kodunisp-lab03.pdf
L#04Wyjątki, funkcje i kolekcjenisp-lab04.pdf
L#05Programowanie obiektowenisp-lab05.pdf
L#06Git, GitHubnisp-lab06.pdf
L#07Gitflownisp-lab07.pdf
L#08Praca zespołowanisp-lab08.pdf
L#09Rozwiązywanie konfliktównisp-lab09.pdf
L#10Code Review i GitHub Pagesnisp-lab10.pdf
L#11Praca zespołowa, Trello, Pull Requestnisp-lab11.pdf
L#12Praca zespołowa, testowanie manualnenisp-lab12.pdf
L#13Architektura klient-server w praktycenisp-lab13.pdf
L#14Przykładowe kolokwiumnisp-lab14.pdf
L#15aKolokwium (grupa A)nisp-lab15a.pdf
L#15bKolokwium (grupa B)nisp-lab15b.pdf
L#15cKolokwium (grupa C)nisp-lab15c.pdf

Testowanie i jakość oprogramowania

Kurs obejmuje zagadnienia dotyczące jakości (wzorce projektowe, refaktoryzacja, code smell) i testowania oprogramowania (testy jednostkowe, integracyjne, mocki, testy e2e).

Testowanie i jakość oprogramowania

Wykłady obejmują wprowadzenie do testowania, praktyki programistyczne, wzorce projektowe, TDD, testy automatyczne oraz zasady jakości oprogramowania. W tabeli poniżej znajdują się główne materiały w formacie PDF.

NrTematPDF
W#01Wprowadzenietijo-lecture01.pdf
W#02Pythontijo-lecture02.pdf
W#03Podstawy Scrumtijo-lecture03.pdf
W#04Flasktijo-lecture04.pdf
W#05Elementy programowania funkcyjnegotijo-lecture05.pdf
W#06Czysty kod, OOP, dobre praktykitijo-lecture06.pdf
W#07SOLID, DRY, KISS, PRAWO DEMETER, CODE SMELLtijo-lecture07.pdf
W#08Wzorce projektowetijo-lecture08.pdf
W#09Podsumowanie(brak PDF)
W#10Wprowadzenie do testowania, piramida testówtijo-lecture10.pdf
W#11Testy jednostkowe, FIRSTtijo-lecture11.pdf
W#12Testy integracyjne, atrapytijo-lecture12.pdf
W#13TDD, E2Etijo-lecture13.pdf
W#14Podsumowanietijo-lecture14.pdf

Testowanie i jakość oprogramowania

Laboratoria obejmują praktyczne ćwiczenia z asercji, testowania jednostkowego, TDD, wzorców projektowych, testów manualnych, selenium, a także QA i AI-driven development. Każde ćwiczenie ma wersję PDF oraz wersję przerobioną do formatu Markdown.

NrTematMateriały
L#01Asercja, Arrange-Act-Assert (AAA)Materiały
L#02Framework unittestMateriały
L#03TDDMateriały
L#04Pokrycie kodu testamiMateriały
L#05SOLIDMateriały
L#06Code SmellsMateriały
L#07Atrapy i Test DoublesMateriały
L#08OOPMateriały
L#09Testy manualneMateriały
L#10Testowanie formularzyMateriały
L#11Test Case & Bug ReportMateriały
L#12SeleniumMateriały
L#13QA & AI-Driven DevelopmentMateriały

Testowanie i jakość oprogramowania

L#01: Asercja, Arrange-Act-Assert (AAA).

Wprowadzenie

W trakcie tego laboratorium zapoznamy się z fundamentalnymi mechanizmami weryfikacji poprawności oprogramowania. Zrozumienie działania asercji oraz poprawnej struktury testu jest kluczowe dla tworzenia oprogramowania wysokiej jakości.

Cel

Głównym celem laboratorium jest opanowanie umiejętności pisania testów jednostkowych przy użyciu asercji oraz wdrożenie standardu Arrange-Act-Assert (AAA) aby poprawić czytelność i organizację kodu testowego.

Asercja

Jest to forma zdaniowa w danym języku, która zwraca prawdę lub fałsz. Asercja wskazuje, że programista zakłada, że ów predykat jest w danym miejscu prawdziwy. W przypadku gdy predykat jest fałszywy (czyli niespełnione są warunki postawione przez programistę) asercja powoduje przerwanie wykonania programu. Asercja ma szczególne zastosowanie w trakcie testowania tworzonego oprogramowania.

Struktura asercji:

result = (2 + 2) < 5
assert result, "2 + 2 nie jest mniejsze od 5. Zweryfikuj kod."

Zastosowanie asercji w praktyce:

def add(first, second):
    return (first + second)


if __name__ == "__main__":
    assert add(1, 2) == 3, "add(1, 2) should return 3"

Postaraj się uruchomić skrypt, następnie zmodyfikuj warunek w taki sposób, aby asercja zwróciła fałsz. Obserwuj co się dzieje w terminalu.

Zadanie do wykonania

Zaimplementuj funkcję def max(digits), która wyszuka największy element z kolekcji liczb całkowitych (digits). Zaproponuj dobre testy / asercje:

  • Test1: Obsługa None (gdy na wejściu pojawi się None to metoda zwraca None).
  • Test2: Obsługa pustej kolekcji (gdy na wejściu pojawi się pusta kolekcja metoda zwraca None).
  • Test3: Obsługa kolekcji jednoelementowej (metoda zwraca największy element).
  • Test4: Obsługa kolekcji wieloelementowej (metoda zwraca największy element).

Arrange-Act-Assert (AAA)

Arrange-Act-Assert (AAA) to technika opisu testów, która pomaga w tworzeniu klarownych, czytelnych i zrozumiałych przypadków testowych. Jest to często stosowany format, który ułatwia organizację testów poprzez podział na trzy etapy: przygotowanie warunków początkowych (Arrange), wykonanie testowanej operacji (Act) oraz weryfikację oczekiwanych rezultatów (Assert).

Zastosowanie Arrange-Act-Assert w praktyce:

def add(first, second):
    return first + second


def test_addition():
    # Arrange
    first_number = 1
    second_number = 2

    # Act
    result = add(first_number, second_number)

    # Assert
    assert result == 3, "add(1, 2) should return 3"

Zadanie do wykonania

Podziel swój kod z poprzedniego zadania na kod produkcyjny (lokalizacja src) i testowy (lokalizacja test). Asercje powinny znaleźć się w oddzielnych funkcjach (jedna asercja na funkcję) oraz powinny być zapisane zgodnie z konwencją Arrange-Act-Assert.

Zadanie dodatkowe

Zaimplementuj funkcję def is_pesel_correct(pesel_digits: list[int]), która zweryfikuje, czy podany numer PESEL jest poprawny. Zaproponuj dobre testy. Zastosuj poznane zagadnienia podczas laboratorium.

Podsumowanie

Podczas tych zajęć omówiliśmy pojęcie asercji jako narzędzia do przerywania programu w przypadku niespełnienia założeń logicznych. Nauczyliśmy się również, jak dzielić test na trzy logiczne fazy (AAA), co znacząco ułatwia późniejszą konserwację i analizę błędów w kodzie.

Testowanie i jakość oprogramowania

L#02: Framework unittest.

Wprowadzenie

Testowanie jednostkowe to fundament tworzenia niezawodnego oprogramowania. Framework unittest jest standardowym narzędziem do testów jednostkowych w ekosystemie Pythona. Dostarcza on silnik do uruchamiania testów oraz bogaty zestaw asercji. Pozwala na separację logiki testowej od produkcyjnej oraz automatyzację procesu weryfikacji zmian w kodzie.

Cel

Celem laboratorium jest zapoznanie się z architekturą testów w frameworku unittest. Skupimy się na izolacji przypadków testowych poprzez metody cyklu życia (setUp, tearDown), weryfikacji sytuacji wyjątkowych oraz stosowaniu spójnych konwencji nazewniczych. Na przykładzie klasy koszyka zakupowego przećwiczymy projektowanie testów dla złożonej logiki biznesowej.

Framework unittest

Spójrz na podstawową strukturę testu przy użyciu tego frameworka. Postaraj się przeanalizować kod, a następnie dokończyć implementacje testów (nie zapominając o konwencji AAA) oraz klasy Calc.

import unittest
from src.calc import Calc


class TestCalc(unittest.TestCase):
    def setUp(self):
        print("* setUp()")
        self.calc = Calc()

    def test_should_add_two_numbers(self):
        print("** test_should_add_two_numbers()")
        result = self.calc.add(3, 2)
        self.assertEqual(result, 5)

    def test_should_raise_error_when_division_by_zero(self):
        print("** test_should_raise_error_when_division_by_zero()")
        with self.assertRaises(ValueError):
            self.calc.divide(10, 0)

    def tearDown(self):
        print("*** tearDown()")
        self.calc = None


if __name__ == "__main__":
    unittest.main()

Zaimplementuj brakujące metody w klasie Calc (add(), subtract(), multiply(), divide()). Po uruchomieniu testów przeanalizuj logi widoczne w konsoli.

Struktura testów

  • W pierwszej kolejności importujemy bibliotekę unittest, która zawiera funkcje do testowania.
  • Każdy test jednostkowy w unittest musi być zawarty w klasie, która dziedziczy po unittest.TestCase.
  • Metoda setUp() jest wywoływana przed każdym testem. Jest to miejsce, gdzie inicjalizujemy obiekty lub zasoby, które będą używane w testach.
  • Każda metoda testowa musi zaczynać się od test_. Jest to konwencja, którą unittest wykorzystuje do rozpoznawania metod, które są testami. Każda metoda testowa sprawdza jedną, konkretną funkcjonalność.
  • assertEqual() to najczęściej używana metoda do porównywania oczekiwanego wyniku z wynikiem rzeczywistym. Sprawdza, czy oba argumenty są sobie równe.
  • assertRaises() jest używana do testowania, czy w odpowiednich sytuacjach jest rzucany wyjątek (np. ZeroDivisionError przy dzieleniu przez zero).
  • tearDown() jest wywoływana po każdym teście i służy do zwalniania zasobów lub zamykania połączeń.
  • Testy uruchamiamy za pomocą unittest.main(), co powoduje automatyczne wykrycie i uruchomienie wszystkich metod testowych.

Nazewnictwo testów

Poprawne nazywanie plików, klas i metod testowych jest kluczowe dla utrzymania porządku w projekcie oraz szybkiej analizy wyników testów.

Element strukturyWymóg technicznyPrzykładowa konwencja klasyczna
Nazwa plikutest_*.py lub *_test.pytest_user_service.py
Nazwa klasyTest* (zalecane)TestUserAuthentication
Nazwa metodytest_* (wymagane)test_invalid_password_rejection

Wybór stylu nazewnictwa metod wpływa na czytelność raportów generowanych przez narzędzia testowe.

Styl nazewnictwaPrzykładowa nazwa metody
Minimalistycznytest_add
BDD (Should)test_should_add_two_positive_integers
Fact-basedtest_adds_two_positive_integers
Given-When-Thentest_given_two_ints_when_added_then_sum_is_correct

Ważne: Niezależnie od wybranego stylu, kluczowe jest trzymanie się jednej konwencji w obrębie całego projektu. Zapewnia to spójność i ułatwia pracę innym programistom.

Uruchomienie testów

Po poprawnym zaimplementowaniu testów oraz klasy produkcyjnej, możemy przystąpić do ich uruchomienia. Poniżej zaprezentowano przykładowy widok z konsoli po pomyślnym wykonaniu wszystkich przypadków testowych.

Zadanie do wykonania

Twoje zadanie będzie polegało na implementacji koszyka zakupowego oraz zestawu testów jednostkowych. Poniżej znajduje się kod źródłowy, który definiuje oczekiwaną strukturę klasy.

class ShoppingCart:
    def add_product(self, product_name: str, price: int, quantity: int) -> bool:
        """Dodawanie produktu do koszyka.

        Parametr 'product_name' traktujemy jak identyfikator, nie można dodać
        nowego produktu o tym samym identyfikatorze. Metoda powinna zwrócić
        False jeżeli przekażemy produkt, który już istnieje w koszyku.
        """
        # 'pass' pozwala na utworzenie pustego bloku, gdy nie ma implementacji.
        # Do usunięcia.
        pass

    def remove_product(self, product_name: str) -> bool:
        """Usuwanie produktu z koszyka"""
        pass

    def update_quantity(self, product_name: str, new_quantity: int) -> bool:
        """Aktualizacja ilości produktu w koszyku"""
        pass

    def get_products(self):
        """Pobieranie nazw produktów z koszyka"""
        pass

    def count_products(self) -> int:
        """Pobieranie liczby produktów znajdujących się w koszyku"""
        pass

    def get_total_price(self) -> int:
        """Pobieranie sumy cen produktów w koszyku"""
        pass

    def apply_discount_code(self, discount_code: str) -> bool:
        """Zastosowanie kuponu rabatowego. Jaką formę promocji proponujesz?"""
        pass

    def checkout(self) -> bool:
        """Realizacja zamówienia.

        W tym miejscu proponuję zaimplementować logikę, która będzie symulowała
        proces zakupu. Metoda zwraca True, jeżeli zamówienie zostało
        zrealizowane pomyślnie, a False w przeciwnym wypadku (np. brak
        produktów w koszyku).
        """
        pass

Pamiętaj, aby przed implementacją konkretnej metody napisać dla niej test (o technice TDD szerzej opowiemy sobie na kolejnych zajęciach). Zastosuj poznaną konwencję Arrange-Act-Assert w każdej metodzie testowej.

Podsumowanie

Opanowanie frameworka unittest pozwala na budowę solidnej siatki bezpieczeństwa dla kodu. Kluczowym elementem jest nie tylko sama weryfikacja wyników, ale także dbałość o czytelność raportów poprzez precyzyjne nazewnictwo oraz zachowanie izolacji testów. Takie podejście minimalizuje ryzyko regresji i ułatwia późniejszą refaktoryzację kodu.

Testowanie i jakość oprogramowania

L#03: TDD.

Wprowadzenie

Testowanie oprogramowania to nie tylko weryfikacja gotowego kodu. W nowoczesnym podejściu proces ten potrafi dyktować architekturę samej aplikacji, gwarantując, że każdy napisany fragment kodu bezpośrednio realizuje założone odgórnie wymagania biznesowe i jest od samego początku pokryty testami.

Cel

Głównym celem laboratorium jest opanowanie techniki Test-Driven Development (TDD) oraz wdrożenie w praktyce cyklu wytwarzania oprogramowania Red-Green-Refactor. Będziemy trenować krok po kroku pisanie testów przed kodem produkcyjnym i refaktoryzację rozwiązań.

Technika TDD

TDD, czyli Test-Driven Development jest to technika tworzenia oprogramowania, w której najpierw tworzone są testy dla nowej funkcjonalności, a dopiero później implementowana jest sama funkcjonalność, aby testy przeszły pomyślnie. Proces ten składa się z 3 głównych kroków.

  • RED: Napisz test (testy nie przechodzą, brak implementacji funkcjonalności).
  • GREEN: Dodaj minimalną implementację, aby testy się powiodły.
  • REFACTOR: Zrefaktoryzuj kod do najprostszej implementacji, aby spełniał oczekiwane standardy (testy przechodzą).

Technika została stworzona przez Kenta Becka.

Poniższy film prezentuje technikę TDD w praktyce. Przepisz kod, dopisz brakujące testy (dodawanie wielu zadań oraz usuwanie zadania). Zaktualizuj implementację klasy TaskList zgodnie z poznaną techniką.

Powyższy przykład demonstruje użycie TDD (Test-Driven Development) w Pythonie. Zaczynamy od napisania testu (RED), który opisuje oczekiwane zachowanie kodu, który jeszcze nie istnieje. Następnie piszemy minimalną implementację (GREEN), która sprawia, że test przechodzi. Na koniec refaktoryzujemy kod (REFACTOR), aby poprawić jego jakość, nie zmieniając jego funkcjonalności.

Zadanie do wykonania

System zarządzania studentami AT

Twoim zadaniem będzie implementacja programu zarządzającego studentami przy użyciu techniki TDD (ang. Test-Driven Development). Aplikacja powinna umożliwiać dodawanie, aktualizowanie, usuwanie studentów, wprowadzanie ocen oraz obliczanie średniej ocen z przedmiotu.

Kod początkowy projektu:

# student_management.py

class StudentManagement:
    """Klasa zarządzająca studentami i ich ocenami."""

    def add_student(self, student_id: str, name: str, age: int) -> bool:
        """Dodaje nowego studenta do bazy danych.

        Args:
            student_id: unikalny identyfikator studenta.
            name: imię studenta.
            age: wiek studenta.

        Returns:
            True, jeśli dodanie zakończyło się sukcesem.
            False w przeciwnym wypadku.
        """
        pass  # Implementacja dodawania studenta

    def update_student(self, student_id: str, name: str, age: int) -> bool:
        """Aktualizuje dane istniejącego studenta na podstawie identyfikatora.

        Args:
            student_id: unikalny identyfikator studenta.
            name: imię studenta.
            age: wiek studenta.

        Returns:
            True, jeśli aktualizacja zakończyła się sukcesem.
            False w przeciwnym wypadku.
        """
        pass  # Implementacja aktualizacji studenta

    def remove_student(self, student_id: str) -> bool:
        """Usuwa studenta z bazy danych na podstawie jego identyfikatora.

        Args:
            student_id: unikalny identyfikator studenta.

        Returns:
            True, jeśli usunięcie zakończyło się sukcesem.
            False w przeciwnym wypadku.
        """
        pass  # Implementacja usuwania studenta

    def add_grade(self, student_id: str, subject: str, grade: float) -> bool:
        """Dodaje ocenę z danego przedmiotu dla określonego studenta.

        Args:
            student_id: unikalny identyfikator studenta.
            subject: nazwa przedmiotu.
            grade: ocena.

        Returns:
            True, jeśli dodanie oceny zakończyło się sukcesem (2.0, 3.0, 3.5, 4.0, 4.5, 5.0).
            False w przeciwnym razie.
        """
        pass  # Implementacja dodawania oceny

    def avg_grades(self, subject: str) -> float:
        """Oblicza średnią ocen z danego przedmiotu dla wszystkich studentów.

        Args:
            subject: nazwa przedmiotu.

        Returns:
            Średnia ocen z przedmiotu jako liczba zmiennoprzecinkowa.
        """
        pass  # Implementacja obliczania średniej ocen

Podsumowanie

Dzięki technice TDD twój kod zyska na jakości, będzie lepiej przetestowany, a Ty nabierzesz pewności, dodając nowe funkcjonalności lub wprowadzając refaktoryzację. Pamiętaj o cyklu Red-Green-Refactor i konsekwentnym nazywaniu testów.

Testowanie i jakość oprogramowania

L#04: Pokrycie kodu testami.

Wprowadzenie

Pokrycie kodu testami (ang. code coverage) to mierzalna metryka stosowana w inżynierii oprogramowania, która określa, jaki procent linii kodu źródłowego został wykonany (skontrolowany) przez testy automatyczne. Narzędzia do mierzenia pokrycia kodu pomagają zidentyfikować obszary aplikacji, które nie są jeszcze chronione przed potencjalnymi błędami.

Cel

Głównym celem tego laboratorium jest poznanie technik analizy i zwiększania pokrycia kodu testami. Nauczymy się generować powiązane raporty w środowisku programistycznym (IDE) oraz interpretować ich wyniki. Wykonując ćwiczenia praktyczne postaramy się osiągnąć maksymalne (100%) pokrycie dla wybranych algorytmów.

Pokrycie kodu testami w praktyce

Istnieje kilka rodzajów metryk oceniających pokrycie – można sprawdzać pokrycie linii (czy dana linijka została wykonana), jak i pokrycie rozgałęzień (czy sprawdzono wszystkie ścieżki warunków logicznych takich jak if/else). W naszym przypadku skupimy się na podstawowej analizie pokrycia bezpośrednio w IDE.

Implementacja

Utwórz nowy projekt w PyCharm i umieść w pakiecie produkcyjnym implementację klasy QuadraticEquation.

import math


class QuadraticEquation:
    def __init__(self, a: float, b: float, c: float):
        if a == 0:
            raise ValueError("Współczynnik 'a' nie może być zerowy w równaniu kwadratowym.")
        self.a = a
        self.b = b
        self.c = c

    def solve(self):
        delta = self.b ** 2 - 4 * self.a * self.c
        if delta > 0:
            x1 = (-self.b + math.sqrt(delta)) / (2 * self.a)
            x2 = (-self.b - math.sqrt(delta)) / (2 * self.a)
            return x1, x2
        elif delta == 0:
            x = -self.b / (2 * self.a)
            return (x,)
        else:
            return None  # Brak pierwiastków rzeczywistych

Umieść w pakiecie testowym implementację klasy TestQuadraticEquation.

import unittest
from src.quadratic_equation import QuadraticEquation


class TestQuadraticEquation(unittest.TestCase):
    def test_should_raise_error_when_a_is_zero(self):
        # arrange
        a, b, c = 0, 2, 4

        # act & assert
        self.assertRaises(ValueError, QuadraticEquation, a, b, c)


if __name__ == '__main__':
    unittest.main()

Testy z raportem

Postaraj się uruchomić testy z raportem pokrycia kodu testami. Przejedź do skryptu z testami i kliknij w zieloną strzałkę (obok klasy) i wybierz opcję widoczną na poniższym rysunku.

Analiza

Po uruchomieniu testów zwróć uwagę na statystyki pokrycia kodu w kodzie klasy QuadraticEquation. Kolor czerwony wskazuje linie, które nie zostały pokryte testami. Kolor zielony wskazuje linie, które zostały pokryte testami.

Mamy 33% pokrycia kodu testami. Dopisz pozostałe testy i zwiększ pokrycie kodu.

Zadanie do wykonania

Twoje zadanie będzie polegało na implementacji operacji na bankomacie. Skorzystaj z przygotowanej poniżej struktury klasy (wraz z dokumentacją metod). Pamiętaj, aby pisać kod metodą TDD. Podczas implementacji i uruchamiania testów analizuj i badaj pokrycie kodu testami.

Dla każdego cyklu stosuj odpowiednią strukturę commiów, np.:

  • RED: implementacja testów dla weryfikacji salda
  • GREEN: implementacja metody check_balance
  • REFACTOR: refaktoryzacja kodu metody check_balance

Kod początkowy (atm.py):

class ATM:
    """Klasa reprezentująca bankomat (ATM) z podstawowymi operacjami bankowymi."""

    def __init__(self, pin: int, initial_balance: float = 0.0):
        """Inicjalizuje bankomat z podanym saldem początkowym.

        :param initial_balance: Saldo początkowe konta.
        :raises ValueError: Jeśli saldo początkowe jest ujemne.
        """
        pass

    def check_balance(self, pin: int) -> float:
        """Sprawdza saldo konta użytkownika.

        :param pin: PIN użytkownika.
        :return: Saldo konta użytkownika.
        :raises InvalidPinException: Jeśli podany PIN jest nieprawidłowy.
        """
        pass

    def deposit(self, pin: int, amount: float) -> float:
        """Wpłaca środki na konto użytkownika.

        :param pin: PIN użytkownika.
        :param amount: Kwota do wpłacenia.
        :return: Aktualne saldo po wpłacie.
        :raises InvalidPinException: Jeśli podany PIN jest nieprawidłowy.
        """
        pass

    def withdraw(self, pin: int, amount: float) -> float:
        """Wypłaca środki z konta użytkownika.

        :param pin: PIN użytkownika.
        :param amount: Kwota do wypłacenia.
        :return: Aktualne saldo po wypłacie.
        :raises InsufficientFundsException: Jeśli saldo jest niewystarczające.
        :raises InvalidPinException: Jeśli podany PIN jest nieprawidłowy.
        """
        pass

Podsumowanie

Dążenie do wysokiego stopnia pokrycia kodu testami zwiększa jakość całego systemu informatycznego. Warto jednak pamiętać, że nawet 100% pokrycia nie gwarantuje całkowicie bezbłędnej aplikacji. W teście liczy się jakość asercji, a sama metryka służy jedynie jako wsparcie i nawigacja pomagająca odnaleźć obszary, które testy automatyczne jeszcze nie pokryły.

Testowanie i jakość oprogramowania

L#05: SOLID.

Wprowadzenie

Zasady SOLID to pięć kluczowych reguł projektowania obiektowego. Dzięki nim kod jest bardziej elastyczny, czytelny i łatwiejszy w utrzymaniu. Stosowanie tych zasad znacznie zmniejsza ryzyko błędów przy rozbudowie aplikacji.

Cel

Głównym celem laboratorium jest nauka rozpoznawania wadliwego kodu, który łamie dobre praktyki. Dodatkowo zapoznamy się z praktycznym zastosowaniem refaktoryzacji zgodnie z zasadami SOLID.

Zasady SOLID

Poniżej przedstawiono opis poszczególnych zasad składających się na akronim SOLID:

  • Single Responsibility Principle (SRP) - Zasada jednej odpowiedzialności: Klasa powinna mieć tylko jedną odpowiedzialność, jeden powód do zmiany.
  • Open/Closed Principle (OCP) – Zasada otwarte/zamknięte: Klasy powinny być otwarte na rozszerzenia, ale zamknięte na modyfikacje.
  • Liskov Substitution Principle (LSP) – Zasada podstawienia Liskov: Obiekty klasy bazowej powinny być zastępowane obiektami klasy pochodnej bez wpływu na poprawność działania programu.
  • Interface Segregation Principle (ISP) – Zasada segregacji interfejsów: Klasy nie powinny zależeć od metod, których nie używają.
  • Dependency Inversion Principle (DIP) – Zasada odwrócenia zależności: Moduły wysokopoziomowe nie powinny zależeć od modułów niskopoziomowych. Oba powinny zależeć od abstrakcji.

Refaktoryzacja

Pobierz wszystkie skrypty i postaraj się je poprawić tak, aby nie naruszały zasad SOLID.

  • Naruszona zasada ⬇️ SRP (zamówienia).
    Czy nasza klasa nie ma zbyt wielu odpowiedzialności? Jak to sprytnie rozdzielić?
  • Naruszona zasada ⬇️ OCP (figury geometryczne).
    Co się stanie, gdy dodamy nową figurę? Czy zostaniesz zmuszony(a) do modyfikacji już działającego kodu?
  • Naruszona zasada ⬇️ LSP (konta bankowe).
    Czy dziedziczenie to na pewno dobry pomysł? Jak zadbać o odpowiedni kontrakt?
  • Naruszona zasada ⬇️ ISP (pracownicy).
    Dlaczego zmuszamy obiekty do wdrażania metod, których nigdy nie użyją? Jak rozbić ten pękaty interfejs?
  • Naruszona zasada ⬇️ DIP (urządzenia).
    Czy zwykły włącznik światła musi być połączony na sztywno z konkretną żarówką? A co jak zechcesz podpiąć do niego wentylator?

Podsumowanie

Zrozumienie i umiejętne stosowanie zasad SOLID to klucz do bycia profesjonalnym inżynierem oprogramowania. Kod oparty na dobrych praktykach ułatwia pracę nie tylko twórcy, ale całemu zespołowi. Regularna praktyka poprzez analizę i poprawę architektury prowadzi do pisania czystego, niezawodnego kodu (clean code).

Testowanie i jakość oprogramowania

L#06: Code Smells.

Wprowadzenie

Code Smell to termin używany w programowaniu do opisywania pewnych cech kodu źródłowego, które wskazują na potencjalne problemy z jego jakością. Niekoniecznie oznaczają one błędy, ale często prowadzą do trudniejszego utrzymania kodu.

Cel

Głównym celem laboratorium jest identyfikacja najczęstszych “zapachów” kodu (ang. Code Smells) oraz nauka ich eliminowania poprzez odpowiednią refaktoryzację struktury kodu.

Rozrosty

  • Długa metoda: Jeżeli metoda jest dłuższa niż 10-20 linii dziel na mniejsze metody.
  • Długa lista parametrów: Jeżeli funkcja ma więcej niż 3-4 parametry, rozważ użycie obiektu.
  • Obsesja na punkcie prymitywów: Używanie powiązanych ze sobą typów prymitywnych zamiast klas. Stwórz klasę / strukturę, która będzie agregować te parametry.

Zbędne elementy

  • Zduplikowany kod: Powtarzający się kod w kilku miejscach wyciągnij do wspólnej metody.
  • Martwy kod: Nieużywane zmienne lub funkcje, usuń je.
  • Leniwa klasa: Klasa, która nie robi nic szczególnego, połącz ją z inną klasą lub usuń.

Łatwe do wykrycia powiązania

  • Zbitki danych: Duplikacja tych samych parametrów w kilku miejscach. Stwórz logiczną struktrę, która będzie agregować te parametry.
  • Zazdrość o funkcje: Metoda operuje głównie na danych innej klasy. Przenieś ją do klasy, których danych używa.

Nadużycia

  • Instrukcje warunkowe: Długi switch/if-else zastąp polimorfizmem lub mapą.
  • Magiczne liczby: Stałe jak 42 bez wyjaśnienia zdefiniuj jako nazwane stałe.

Zadanie rekrutacyjne

Wykorzystaj dotychczas zdobytą wiedzę i postaraj się rozwiązać problem. Napisz testy oraz zaimplementuj rozwiązanie.

Proszę zaimplementować program, który będzie odpowiedzialny za wyszukiwanie zbiorów liczb powtarzających się elementów o ściśle określonym rozmiarze. Dla podanego zbioru liczb (lista elementów o dowolnej długości) użytkownik powinien przekazać również rozmiar wyszukiwanych zbiorów. Funkcja powinna zwracać listę składającą się z pojedynczych elementów reprezentujących wyszukiwane zbiory.

PARAMETRY FUNKCJI LOTTERYEFEKT DZIAŁANIAREZULTAT
[1, 1, 3, 2, 2, 2, 4, 5], 2[1, 1, 3, 2, 2, 2, 4, 5][1]
[1, 1, 2, 2, 2, 3, 4, 5], 3[1, 1, 2, 2, 2, 3, 4, 5][2]
[1, 2, 2, 2, 3, 4, 5, 5, 1], 2[1, 2, 2, 2, 3, 4, 5, 5, 1][1, 5]
None, 1[][]
[1, 2, 3], None[][]
None, None[][]
[1, 1, 2, 2, 2, 3, 4, 5], 7[][]

Realne zadanie rekrutacyjne do firmy schibsted.

Pojazd księżycowy

Jako inżynier firmy NASA zostałeś poproszony o zaprojektowanie, przetestowanie oraz implementację ruchu pojazdu księżycowego. Musisz być świadomy ograniczeń, które zostały uwzględnione w specyfikacji technicznej.

Specyfikacja techniczna pojazdu księżycowego:

PRZESTRZEŃ PRACYZACHOWANIE W PRZESTRZENI 2D
Jazda do przodu.Możliwa o dowolną liczbę pól.
Jazda do tyłu.Możliwa o dowolną liczbę pól.
Skręt w lewo.Brak tradycyjnego mechanizmu skrętu.
Skręt w prawoBrak tradycyjnego mechanizmu skrętu.
Rotacja / obrót wokół własnej osi.Możliwy. Ruch oznacza obrót o 90° w lewo lub w prawo.
Punkt startu.Punkt początkowy. Punkt odniesienia pojazdu.
Odczyt lokalizacji.Pojazd zwraca współrzędne X i Y obszaru, w którym się znajduje.

Bardzo proszę zaproponować interfejs pojazdu księżycowego dostosowany do specyfikacji technicznej. Proszę zaimplementować mechanizm poruszania się pojazdu księżycowego. Zachowanie pojazdu powinno być dobrze przetestowane przy pomocy modułu unittest.

Podsumowanie

Umiejętność rozpoznawania i naprawiania Code Smells jest niezbędna przy tworzeniu łatwego w utrzymaniu oprogramowania. Zrozumienie opisanych w laboratorium złych praktyk i ich świadome unikanie znacznie zredukuje przyszły czas poświęcony na refaktoryzację kodu źródłowego.

Testowanie i jakość oprogramowania

L#07: Atrapy.

Wprowadzenie

Atrapy są to obiekty zastępcze, które ułatwiają testowanie projektów. Pozwalają wydzielić kod od zawiłych zależności, takich jak bazy danych czy systemy plików. Dają pełną kontrolę nad otoczeniem testowanego kodu. Ułatwiają tym samym sprawdzanie logiki.

Rozróżniamy pięć głównych typów atrap.

  • Dummy służy do zastąpienia obiektu, który jest wymagany jako parametr, ale nie jest używany w testowanej metodzie.
  • Stub służy do podmieniania zachowania obiektu, aby zwracał z góry określone wartości.
  • Fake jest to atrapa, która posiada własną implementację, ale nie jest to rzeczywista implementacja.
  • Spy bazuje na prawdziwym obiekcie, ale opakowuje go i zapisuje informacje o jego wywołaniach. W języku Python nie ma dedykowanej klasy Spy, ale można ją zaimplementować za pomocą Mock.
  • Mock bazuje na pustym obiekcie, ale możemy zdefiniować jego zachowanie i sprawdzić jego wywołania.

Wykorzystujemy je jako obiekty zastępcze w testach.

Wskazówka: Warto zauważyć, że język Python (biblioteka unittest.mock) nie dzieli atrap na tak sztywne klasyfikacje. Klasa Mock pełni najczęściej rolę uniwersalnego zamiennika (np. jako Dummy, Stub, czy Spy). Dlatego na potrzeby tego laboratorium i zachowania czytelności kodu, wykluczyłem niektóre z nich i skupimy się na nauce oraz praktycznym wykorzystaniu Dummy, Fake oraz Mock.

Cel

Celem laboratorium jest zapoznanie się z atrapami i ich zastosowaniem w testach.

Oto zadania dla Ciebie:

  • Refaktoryzacja kodu: Oddziel kod produkcyjny(src) od testowego(test). Rozbij skrypt na mniejsze moduły i umieść je w odpowiednich katalogach. W katalogu produkcyjnym utwórz podkatalogi model, view, controller.
  • Implementacja: Dokończ implementację wszystkich metod w kodzie produkcyjnym. Nie zmieniaj testów! Po uruchomieniu zestawu testów zauważysz, że nie przechodzą ze względu na brak implementacji logiki szyfru Cezara. Pracuj zgodnie z techniką TDD (Test-Driven Development). Skup się na zaprogramowaniu logiki (wyszukaj komentarze TODO), aby testy przeszły, a dopiero potem zajmij się refaktoryzacją. Każda zaimplementowana funkcjonalność to jeden commit, więc zatwierdzaj aplikację etapami.
  • Użyj ChatBota: Wykorzystaj ChatBota do refaktoryzacji kodu i implementacji, ale nie generuj gotowego rozwiązania. Zamiast tego, proś o pomoc w poszczególnych krokach.
  • Analiza atrap: Przeanalizuj kod i zwróć uwagę, w jaki sposób wykorzystywane są atrapy.

Wzorzec MVC

Wzorzec MVC (Model-View-Controller) to wzorzec architektoniczny, który polega na podziale kodu programu na trzy oddzielne moduły. Model reprezentuje dane i logikę biznesową. View to interfejs użytkownika. Controller to pośrednik między modelem a widokiem.

Aplikacja - szyfr Cezara

# main.py
import tkinter as tk
from tkinter import messagebox
import unittest
from unittest.mock import Mock, call

# --- MODEL BIZNESOWY (Model) ---
class Logger:
    """Prosty system logowania."""
    def info(self, msg: str) -> None:
        print(f"[INFO] {msg}")
        
    def error(self, msg: str) -> None:
        print(f"[ERROR] {msg}")

class FileHandler:
    """Obsługa plików."""
    def read_content(self, filepath: str) -> str:
        # TODO: Zaimplementuj odczyt
        raise NotImplementedError("Odczyt z pliku nie jest zaimplementowany.")
        
    def write_content(self, filepath: str, content: str) -> None:
        # TODO: Zaimplementuj zapis
        raise NotImplementedError("Zapis do pliku nie jest zaimplementowany.")

class CaesarCipher:
    """Logika kryptograficzna."""
    def __init__(self, shift: int):
        self.shift = shift

    def encrypt(self, text: str) -> str:
        # TODO: Zaimplementuj szyfr Cezara
        raise NotImplementedError("Logika szyfrowania nie jest gotowa.")

class CryptoModel:
    """Mózg operacyjny. Odcięty od interfejsu."""
    def __init__(self, cipher: CaesarCipher, file_handler: FileHandler, logger: Logger):
        self.cipher = cipher
        self.file_handler = file_handler
        self.logger = logger
        
    def process_file(self, input_path: str, output_path: str) -> bool:
        """Kieruje logiką przetwarzania danych."""
        try:
            content = self.file_handler.read_content(input_path)
            encrypted = self.cipher.encrypt(content)
            self.file_handler.write_content(output_path, encrypted)
            self.logger.info(f"Sukces w lokalizacji: {output_path}")
            return True
        except Exception as e:
            self.logger.error(f"Wystąpił błąd: {e}")
            return False

# --- WIDOK (View) ---
class AppView:
    """Warstwa prezentacji (Tkinter). Nie wie nic o szyfrowaniu."""
    def __init__(self, root):
        self.root = root
        
        # Interfejs okna.
        tk.Label(root, text="Ścieżka pliku wejściowego:").pack(pady=(10, 0))
        self.input_entry = tk.Entry(root, width=35)
        self.input_entry.insert(0, "tajne_hasla.txt")
        self.input_entry.pack(pady=5)

        tk.Label(root, text="Ścieżka pliku wyjściowego:").pack(pady=(10, 0))
        self.output_entry = tk.Entry(root, width=35)
        self.output_entry.insert(0, "wynik_szyfrowania.txt")
        self.output_entry.pack(pady=5)
        
        self.action_button = tk.Button(root, text="Szyfruj plik")
        self.action_button.pack(pady=20)
        
    def get_input_path(self) -> str:
        # Pobieranie tekstu widgetu.
        return self.input_entry.get()
        
    def get_output_path(self) -> str:
        # TODO: Odbierz wartość przypisaną z powyższego pola.
        return "wyjście.txt"
        
    def show_message(self, success: bool):
        # TODO: Wygeneruj okno messagebox.showinfo lub messagebox.showerror bazując na fladze.
        pass

    def bind_action(self, callback):
        # TODO: Przypisz zdarzenie zaprogramowanego przycisku.
        pass

# --- KONTROLER (Controller) ---
class AppController:
    """Spaja widok z modelem reagując na zdarzenia."""
    def __init__(self, model: CryptoModel, view: AppView):
        self.model = model
        self.view = view
        self.view.bind_action(self.handle_encryption)

    def handle_encryption(self):
        """Zarządza logiką tuż po kliknięciu, wywołując poszczególne akcje modelu."""
        in_path = self.view.get_input_path()
        out_path = self.view.get_output_path()
        result = self.model.process_file(in_path, out_path)
        self.view.show_message(result)

# --- SEKCJA TESTÓW ---
class TestMVCComponents(unittest.TestCase):

    # Wykorzystana atrapa: Dummy
    def test_should_process_file_without_errors(self):
        # Dummy służy do zastąpienia obiektu, który jest wymagany jako 
        # parametr, ale nie jest używany w testowanej metodzie.
        
        # Given
        dummy_logger = Mock() 
        mock_handler = Mock(spec=FileHandler)
        mock_handler.read_content.return_value = "DowolnyTekst"
        real_cipher = CaesarCipher(shift=3)
        model = CryptoModel(real_cipher, mock_handler, dummy_logger)
        
        # When
        result = model.process_file("in.txt", "out.txt")
        
        # Then
        # Uwaga: Dummy spełnił swoją rolę już podczas bezbłędnej inicjalizacji 
        # modelu w Given. Testujemy tu tylko to, że sama obecność pustego 
        # loggera nie spowodowała błędu (wyjątku).
        self.assertTrue(result)

    # Wykorzystana atrapa: Mock
    def test_should_write_encrypted_content_to_output_file(self):
        # Mock bazuje na pustym obiekcie, ale możemy zdefiniować jego 
        # zachowanie i sprawdzić jego wywołania.
        
        # Given
        dummy_logger = Mock()
        mock_file_handler = Mock(spec=FileHandler)
        mock_file_handler.read_content.return_value = "abc"
        real_cipher = CaesarCipher(shift=3)
        model = CryptoModel(real_cipher, mock_file_handler, dummy_logger)
        
        # When
        model.process_file("a.txt", "b.txt")
        
        # Then
        mock_file_handler.write_content.assert_called_once_with("b.txt", "def")

    # Wykorzystana atrapa: Fake
    def test_should_save_data_to_file_system(self):
        # Fake jest to atrapa, która posiada własną implementację, ale nie 
        # jest to rzeczywista implementacja.
        
        # Given
        class InMemoryFileHandler(FileHandler):
            def __init__(self):
                self.storage = {"d/wejscie.txt": "abc"}
            def read_content(self, path: str) -> str:
                if path not in self.storage:
                    raise FileNotFoundError(f"Brak: {path}")
                return self.storage[path]
            def write_content(self, path: str, content: str) -> None:
                self.storage[path] = content
                
        dummy_logger = Mock()
        real_cipher = CaesarCipher(shift=3)
        fake_fs = InMemoryFileHandler()
        model = CryptoModel(real_cipher, fake_fs, dummy_logger)
        
        # When
        model.process_file("d/wejscie.txt", "d/wynik.txt")
        
        # Then
        self.assertIn("d/wynik.txt", fake_fs.storage)
        self.assertEqual(fake_fs.storage["d/wynik.txt"], "def")

if __name__ == "__main__":

    unittest.main() # Uruchamia testy
    
    # Kod uruchomieniowy aplikacji przenieś do pliku main.py 
    # (plik main.py umieść w katalogu src)
    
    # root = tk.Tk()
    # root.title("Kryptografia MVC")
    # root.geometry("400x300")
    # model = CryptoModel(CaesarCipher(3), FileHandler(), Logger())
    # view = AppView(root)
    # controller = AppController(model, view)
    # root.mainloop()

Testowanie i jakość oprogramowania

L#08: OOP.

Wprowadzenie

Programowanie obiektowe (ang. Object-Oriented Programming) to paradygmat programowania, który opiera się na koncepcji obiektów. Obiekty są instancjami klas, które definiują ich właściwości i zachowanie. Programowanie obiektowe umożliwia tworzenie bardziej złożonych i elastycznych aplikacji poprzez organizację kodu w moduły.

Programowanie obiektowe opiera się na kilku kluczowych koncepcjach:

  • Abstrakcja: Proces ukrywania szczegółów implementacji i przedstawiania tylko istotnych cech obiektu.
  • Enkapsulacja: Proces grupowania danych i metod w jedną jednostkę (klasę) oraz ograniczania dostępu do niektórych jej elementów.
  • Dziedziczenie: Mechanizm, który pozwala na tworzenie nowych klas na podstawie istniejących, dziedzicząc ich właściwości i metody.
  • Polimorfizm: Zdolność różnych klas do implementacji tych samych metod, co pozwala na użycie tych samych interfejsów w różnych kontekstach.

Cel

Głównym celem tego laboratorium jest zrozumienie i praktyczne zastosowanie mechanizmów programowania obiektowego. Nauczysz się tworzyć bezpieczne metody dostępowe (gettery i settery), stosować mechanizm kopii defensywnej w celu ochrony integralności obiektów, a także przeprowadzisz refaktoryzację aplikacji webowej we Flasku do struktury zorientowanej obiektowo.

Zadanie - setter()

setter() jest odpowiedzialny za zmianę “wnętrza” obiektu. Jeśli zaimplementujesz go niedbale, może narobić bałaganu. Weryfikuj, czy podajesz sensowne dane, pilnuj, aby wszystko w obiekcie do siebie pasowało po zmianie. Możesz łatwo “zepsuć” swój obiekt i wprowadzić go w zły stan.

Prosty przykład: Wyobraź sobie setter set_age(). Jeśli pozwala ci wpisać -5 lat, to coś jest nie tak z Twoim obiektem user. Masz okazję poprawić implementację poniższej klasy.

class User:
    def __init__(self, name, age):
        self._name = name
        self._age = age
        self._is_adult = self._age >= 18

    def get_name(self):
        return self._name

    def get_age(self):
        return self._age

    def set_age(self, new_age):
        # Problem!
        self._age = new_age


user = User("Jan", 30)
print(f"Początkowy wiek: {user.get_age()}")
user.set_age(-5)
print(f"Wiek po ustawieniu nieprawidłowej wartości: {user.get_age()}")
user.set_age(200)
print(f"Wiek po ustawieniu absurdalnie dużej wartości: {user.get_age()}")

Porady dotyczące tworzenia metod ustawiających.

  • Sprawdzaj, co wpisujesz: Upewnij się, że wiek nie jest ujemny.
  • Pilnuj porządku: Jeśli zmiana wieku wpływa na inne atrybuty (np. status pełnoletności is_adult), setter wieku powinien również zaktualizować ten stan.
  • Pomyśl dwa razy: Czy naprawdę potrzebujesz tylu setterów? Może zamiast zmieniać wszystko po kawałku, lepiej zrobić jedną akcję, która logicznie zmienia stan obiektu.

Zadanie - getter()

getter() jest odpowiedzialny za bezpieczny odczyt danych z “wnętrza” obiektu. Jeśli zaimplementujesz go niedbale, możesz ujawnić zbyt wiele. Getter powinien być prosty, ale przemyślany – upewnij się, że zwraca dane w odpowiedniej formie i nie zdradza więcej, niż powinien.

Klasa Transfer posiada niebezpieczny getter(). Zobacz, jak łatwo można naruszyć integralność kluczowej operacji finansowej z zewnątrz. Obiekt, reprezentujący gotówkę klienta, jest uszkodzony. Napraw go stosując kopię defensywną.

class TimeOfTransfer:
    def __init__(self, hour, minute):
        self.hour = hour
        self.minute = minute

    def __str__(self):
        return f"{self.hour:02d}:{self.minute:02d}"


class Transfer:
    def __init__(self, amount, transfer_time):
        self._amount = amount
        self._transfer_time = transfer_time

    def get_transfer_time(self):
        # Problem!
        return self._transfer_time

    def get_amount(self):
        return self._amount

    def execute_transfer(self):
        print(f"Wykonuje przelew na kwotę {self._amount} o godzinie {self._transfer_time}")


scheduled_time = TimeOfTransfer(14, 30)
my_transfer = Transfer(100.00, scheduled_time)
print(f"Początkowy czas przelewu: {my_transfer.get_transfer_time()}")
my_transfer.execute_transfer()

# Ups! Ktoś dobrał się do czasu przelewu...
time_from_getter = my_transfer.get_transfer_time()
time_from_getter.hour = 16
time_from_getter.minute = 0

print(f"\nCzas przelewu PO ZEWNĘTRZNEJ INGERENCJI: {my_transfer.get_transfer_time()}")
my_transfer.execute_transfer()
print("\nUps! Kluczowy czas obiektu przelewu został zmanipulowany z zewnątrz.")
print("Ot tak, integralność obiektu została naruszona, a to były czyjeś ciężko zarobione pieniądze.")
print("To tylko zwykły getter(), a jak wiele może zepsuć.")

Zadanie - OOP i Flask

Pobierz aplikację: flask-figure-app, skopiuj ją do katalogu źródłowego src i uruchom moduł app.py.

Aplikacja jest prostą aplikacją webową, która pozwala na zmianę kolorów figur geometrycznych. Używa Flask do obsługi żądań HTTP i renderowania szablonu HTML.

Wykonaj refaktoryzację kodu i spełnij wymagania:

  • Zdefiniuj klasy (Figure, Square, Circle, Triangle) reprezentujące figury z atrybutami i metodami.
  • Utwórz kolekcję (np. słownik figures) przechowującą instancje figur.
  • Utwórz dedykowaną klasę (serwis) odpowiedzialną za zarządzanie stanem figur.
  • Zaimplementuj w serwisie metody do pobierania stanu kolorów figur w spójnym formacie (np. słownik).
  • Użyj serwisu w module app.py. Zmodyfikuj funkcje obsługi żądań HTTP, aby korzystały z metod utworzonego serwisu do interakcji z figurami.

Podsumowanie

Odpowiednio zaimplementowane mechanizmy enkapsulacji są niezbędne do zachowania kontroli nad stanem obiektu. Używanie getterów i setterów w sposób świadomy (z weryfikacją poprawności oraz kopiami defensywnymi) zapobiega wstrzykiwaniu nieprawidłowych danych. Refaktoryzacja na paradygmat obiektowy ułatwia zarządzanie i skalowanie aplikacji, co jest szczególnie istotne w projektach webowych.

Testowanie i jakość oprogramowania

L#09: Testy manualne.

Wprowadzenie

Testy manualne to proces testowania oprogramowania, w którym tester ręcznie wykonuje testy, aby sprawdzić, czy aplikacja zachowuje się zgodnie z oczekiwaniami. W testach manualnych tester wykonuje konkretne kroki, aby zweryfikować funkcjonalność aplikacji, identyfikować błędy i oceniać ogólną jakość produktu.

Cel

Głównym celem laboratorium jest zapoznanie się z procesem testowania manualnego w praktyce. Nauczysz się weryfikować działanie aplikacji, analizować jej zachowanie. Dodatkowo przeprowadzisz implementację brakujących funkcji na podstawie analizy wyników testów manualnych.

Aplikacja Chess

Pobierz aplikację chess.zip i dobrze przeanalizuj kod. Po uruchomieniu aplikacji gra będzie dostępna pod adresem http://localhost:5000/.

Jak działa gra?

Z pola typu select wybieramy figurkę, która nas interesuje. Inicjujemy ruch poprzez zaznaczenie figury (klikamy na figurkę).

Następnie klikamy w pole docelowe, gdzie życzymy sobie, aby figurka się przemieściła.

Twoje zadanie

Bardzo proszę dokończyć implementację logiki ruchów figurek na planszy szachowej (ruchy figur szachowych: wikipedia). Wzorujemy się na implementacji, która już istnieje. Aplikacja frontendowa została już zaimplementowana. Ruchy figur powinny być testowane manualnie.

Po zakończonej implementacji zastanów się nad refaktoryzacją kodu. Zwróć uwagę na wielokrotne instrukcje warunkowe realizujące poszczególne ruchy. Czy da się zaimplementować to inaczej? (Podpowiedź: Wykorzystaj polimorfizm).

Podsumowanie

Testy manualne są kluczowym elementem zapewniania jakości oprogramowania, zwłaszcza na wczesnych etapach rozwoju oprogramowania lub przy interfejsach użytkownika, które ciężko w pełni zautomatyzować. Podczas testów wykonywanych ręcznie możemy dostrzec problemy z perspektywy użytkownika końcowego, których nie dostrzeglibyśmy podczas analizy kodu. Pozwalają one również na identyfikację błędów, które nie zostały wykryte podczas testów automatycznych.

Testowanie i jakość oprogramowania

L#10: Testy manualne, testowanie formularzy.

Wprowadzenie

Testy manualne to proces testowania oprogramowania, w którym tester ręcznie wykonuje testy, aby sprawdzić, czy aplikacja zachowuje się zgodnie z oczekiwaniami. W testach manualnych tester wykonuje konkretne kroki, aby zweryfikować funkcjonalność aplikacji, identyfikować błędy i oceniać ogólną jakość produktu.

Cel

Celem laboratorium jest zapoznanie się z procesem testowania formularzy i walidacji danych w praktyce.

Aplikacja Register

Pobierz aplikację register.zip i dobrze przeanalizuj kod. Po uruchomieniu aplikacji formularz rejestracji będzie dostępny pod adresem http://localhost:5000/.

Widok aplikacji po uruchomieniu serwera.

Twoje zadanie

Bardzo proszę przeanalizować kod i dokończyć (poprawić) walidację pozostałych (istniejących) pól formularza rejestracji użytkownika zgodnie z założeniami umieszczonymi w tabelce.

Implementacja walidacji = COMMIT (implementuj funkcjonalnośći etapami, pamiętaj o dobrym opisie commit’a).

POLE FORMULARZAWALIDACJA
LOGINPole nie może być puste. Pole może zawierać dowolny ciąg składający się minimum z 4 znaków.
FIRST_NAMEPole nie może być puste. Pole może zawierać dowolny ciąg.
LAST_NAMEPole nie może być puste. Pole może zawierać dowolny ciąg.
PASSWORDPole nie może być puste. Pole powinno składać się z minimum 4 znaków. Hasło powinno składać się przynajmniej z: Cyfry, wielkiej litery, małej litery, znaku specjalnego (!@#$%^&*()_+-=).
PESELPole nie może być puste. Weryfikacja numeru PESEL powinna zostać oparta o wyliczenie cyfry kontrolnej.

Podsumowanie

Testowanie manualne formularzy to podstawowy i niezbędny element zapewniania jakości każdej aplikacji internetowej. Prawidłowa walidacja zabezpiecza aplikację przed wprowadzaniem niepoprawnych lub niebezpiecznych danych.

Testowanie i jakość oprogramowania

L#11: Test Case & Bug Report.

Wprowadzenie

Test Case (Przypadek Testowy) to dokument służący do weryfikacji, czy system w odpowiedzi na konkretne akcje działa zgodnie z założeniami. Ułatwia systematyczne i powtarzalne testowanie.

Bug Report (Zgłoszenie Błędu) to raport opisujący niezgodność między działaniem faktycznym a oczekiwanym. Precyzyjne zgłoszenie pozwala programiście sprawnie odtworzyć i usunąć usterkę.

Cel

Celem laboratorium jest zapoznanie się z procesem dokumentowania przypadków testowych oraz tworzenia raportów o błędach z wykorzystaniem narzędzia Trello.

Zadanie - Test Case & Bug Reports (Trello)

Masz do dyspozycji dwie aplikacje w wersji DEV (do testowania) i PROD (jako dokumentacja referencyjna):

  • Aplikacja “Kalkulator”: DEV, PROD
  • Aplikacja “Portfolio”: DEV, PROD

Twoim pierwszym krokiem jest założenie konta w aplikacji Trello. Dla każdej aplikacji utwórz oddzielną tablicę, a następnie przeprowadź ich analizę porównawczą (wersja PROD stanowi bezbłędny wzorzec). Wszelkie zauważone różnice w działaniu są kluczem do sporządzenia przypadków testowych (Test Case) i na ich podstawie raportów błędów (Bug Reports).

W każdej tablicy utwórz kolumny (jedna tablica = jeden projekt):

  • TestCase - Kalkulator, 2 karty | Portfolio, 5 kart.
  • Zgłoszenia (BugReports) - Kalkulator, 2 karty | Portfolio, 5 kart.
  • Zgłoszenia w trakcie - Kolumna bez kart.
  • Zgłoszenia zweryfikowane - Kolumna bez kart.

Podsumowanie

Testy pozwalają wykryć błędy i upewnić się, że produkt działa zgodnie z oczekiwaniami użytkowników. Rzetelne dokumentowanie przypadków testowych i zgłaszanie błędów to podstawowe narzędzia testera, które pozwalają na efektywną współpracę z programistami i budowanie produktów o najwyższej jakości.

Testowanie i jakość oprogramowania

L#12: Selenium.

Wprowadzenie

Selenium to biblioteka języka Python służąca do automatyzacji przeglądarek internetowych. Pozwala na sterowanie przeglądarką, symulowanie działań użytkownika oraz testowanie aplikacji webowych.

Do czego wykorzystujemy Selenium?

  • Automatyzacja testów aplikacji webowych.
  • Symulowanie interakcji użytkownika z przeglądarką.
  • Testowanie kompatybilności stron na różnych przeglądarkach.
  • Web scraping (pobieranie danych ze stron internetowych).
  • Tworzenie botów do wykonywania powtarzalnych czynności online.

Co można testować przy pomocy Selenium?

  • Formularze: Testowanie obsługi formularzy, wprowadzania i przesyłania danych.
  • Nawigację: Klikanie w linki, sprawdzanie przekierowań.
  • Elementy interfejsu: Widoczność przycisków, tekstów, ikon.
  • Interakcje użytkownika: Scrollowanie, przeciąganie (drag and drop), alerty.
  • Responsywność: Testy dla różnych rozdzielczości.

Instalacja potrzebnych paczek

pip install selenium webdriver-manager

Przydatne zasoby

Cel

Celem laboratorium jest zapoznanie się z biblioteką Selenium oraz procesem automatyzacji testów webowych w języku Python. Zdobędziesz praktyczne umiejętności pozwalające na tworzenie skryptów, które automatycznie weryfikują działanie aplikacji w przeglądarce, bazując na wcześniej przygotowanych przypadkach testowych.

Zadanie - Selenium

Na podstawie zaprezentowanych poniżej przykładów kodu napisz testy automatyczne dla aplikacji udostępnionych na poprzednim laboratorium. Wykorzystaj bibliotekę Selenium oraz język Python.

Twoim zadaniem będzie zaimplementowanie testów, które będą weryfikowały przypadki testowe oraz zgłoszone błędy (bug reports). Skup się na automatyzacji scenariuszy testowych, które zostały utworzone podczas poprzedniego laboratorium.

  • Przeanalizuj dostępne poniżej skrypty i uruchom je lokalnie.
  • Przeanalizuj swoje przypadki testowe i bug reporty z poprzednich zajęć.
  • Napisz testy automatyczne w Pythonie z użyciem Selenium, które pokrywają te przypadki.
  • Przetestuj swoje rozwiązanie (zweryfikuj, jak zachowują się testy po przełączeniu na środowisko DEV).

Przykłady implementacji testów automatycznych

Poniżej znajdziesz gotowe skrypty, które pomogą Ci zrozumieć podstawowe mechanizmy i rozpocząć pracę.

Weryfikacja nagłówka strony

Prosty test weryfikujący obecność i treść nagłówka H1 na przykładowej stronie.

import unittest
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

class TestWebPage(unittest.TestCase):
    def setUp(self):
        """
        Inicjalizacja testu - uruchomienie przeglądarki Chrome
        """
        self.service = Service(ChromeDriverManager().install())
        self.driver = webdriver.Chrome(service=self.service)

    def test_page_heading(self):
        """
        Test sprawdzający obecność (assertIsNotNone) i zawartość (assertEqual) nagłówka na stronie
        """
        # Given
        self.driver.get('https://example.com')

        # When
        heading = self.driver.find_element(By.TAG_NAME, 'h1')

        # Then
        self.assertIsNotNone(heading)
        self.assertEqual(heading.text, "Example Domain")

        # Zatrzymanie przeglądarki na 3 sekundy (do celów edukacyjnych)
        time.sleep(3)

    def tearDown(self):
        """
        Zakończenie testu - zamknięcie przeglądarki
        """
        self.driver.quit()

if __name__ == '__main__':
    unittest.main()

Obsługa formularza kalkulatora

Test wprowadzający dane do formularza i weryfikujący wynik działania kalkulatora.

import unittest
import time

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

class TestCalculator(unittest.TestCase):
    def setUp(self):
        """
        Inicjalizacja testu - uruchomienie przeglądarki Chrome i otwarcie strony kalkulatora
        """
        self.service = Service(ChromeDriverManager().install())
        self.driver = webdriver.Chrome(service=self.service)
        self.driver.get('https://tgadek.pl/app/tijo-calc/prod/index.html')

    def test_addition(self):
        """
        Test sprawdzający działanie operacji dodawania w kalkulatorze
        """
        # Given
        number1 = self.driver.find_element(By.ID, "number1")
        number1.send_keys("1")
        number2 = self.driver.find_element(By.ID, "number2")
        number2.send_keys("2")

        # When
        self.driver.find_element(By.CSS_SELECTOR, "input[type='button']").click()

        # Then
        result = self.driver.find_element(By.ID, "result").text
        self.assertEqual(result, "1 + 2 = 3")

        # Zatrzymanie przeglądarki na 3 sekundy (do celów edukacyjnych)
        time.sleep(3)

    def tearDown(self):
        """
        Zakończenie testu - zamknięcie przeglądarki
        """
        self.driver.quit()

if __name__ == '__main__':
    unittest.main()

Podsumowanie

Automatyzacja testów za pomocą narzędzi takich jak Selenium znacznie przyspiesza proces weryfikacji oprogramowania, szczególnie przy powtarzalnych testach regresyjnych (testy weryfikujące, czy nowo wprowadzony kod nie popsuł działających już funkcji).

Testowanie i jakość oprogramowania

L#13: QA & AI-Driven Development

Wprowadzenie

Rola inżyniera jakości (QA) dynamicznie ewoluuje. Dziś nowoczesny tester nie tylko manualnie weryfikuje oprogramowanie, ale przede wszystkim projektuje zautomatyzowane procesy z wykorzystaniem AI. Podczas tego laboratorium dowiesz się, jak sprawnie tworzyć własne, inteligentne narzędzia i asystentów znacząco przyspieszających codzienną pracę.

Cel

Praktyczne opanowanie środowiska Gemini (przejdź do Gemini) w celu tworzenia dedykowanych botów (Gems) generujących testy automatyczne. Kolejnym etapem będzie błyskawiczna budowa własnego, przeglądarkowego klienta API z wykorzystaniem interaktywnego panelu Gemini Canvas.

Słownik pojęć

  • Data-Driven Testing (DDT): Technika automatyzacji polegająca na oddzieleniu skryptów testowych od danych (zapisywanych w zewnętrznym pliku np. JSON, YAML lub CSV), co pozwala na wykonywanie tych samych testów dla wielu zestawów danych wejściowych.
  • Gemini Gem: Spersonalizowana wersja asystenta AI, skonfigurowana pod konkretne zadanie za pomocą stałych instrukcji systemowych.
  • System Prompt (Instrukcja systemowa): Główna instrukcja nadająca asystentowi AI rolę, kontekst oraz określająca format wyjściowy i ograniczenia.
  • Gemini Canvas: Zintegrowany, interaktywny edytor wbudowany w Gemini, pozwalający na programowanie, testowanie i edycję kodu bezpośrednio obok okna czatu.

Automatyzacja tworzenia testów z Gemini Gems

Gemini Gem to spersonalizowany asystent AI działający w oparciu o stałe instrukcje. Dzięki nim bot staje się wyspecjalizowanym narzędziem, które nie traci kontekstu projektu podczas kolejnych sesji programistycznych.

Jak utworzyć Gema?
W lewym menu bocznym interfejsu Gemini przejdź do sekcji Gemy (Gems). Należy wybrać opcję + Nowy Gem. Zostaniesz przekirowany do formularza konfiguracji Gema, który składa się z następujących pól:

  • Nazwa (Name): Krótka, identyfikująca nazwa asystenta.
  • Opis (Description): Zwięzła informacja o przeznaczeniu bota.
  • Instrukcje (Instructions): Najważniejsze pole (system prompt), które decyduje o zachowaniu AI. Wklejamy tu rygorystyczne wytyczne określające rolę, styl pracy oraz ograniczenia bota.
  • Wiedza: Pliki lub zrzuty ekranu, które mają być wykorzystywane przez bota jako kontekst w procesie tworzenia kodu.
  • Podgląd: Pole do testowania stworzonego bota.

Kluczem do sukcesu przy generowaniu testów jest podanie botowi precyzyjnej sygnatury metody, wymagań biznesowych i wymuszenie w promptach (instrukcjach Gema) rygorystycznego zwracania wyłącznie kodu źródłowego (bez opisów). Zmusza to model do wygenerowania gotowego do wdrożenia kodu testów, eliminując niepotrzebny szum informacyjny.

Zadania do wykonania

Zadanie 1: Budowa bota odpowiedzialnego za tworzenie testów
Utwórz Gema Senior QA Test Generator, którego wyłącznym celem jest generowanie testów w bibliotece unittest dla języka Python na podstawie dostarczonych wymagań biznesowych i sygnatury. Upewnij się, że bot zwraca wyłącznie kod źródłowy. Kluczowe jest, aby w polu Instrukcje wyegzekwować od bota stosowanie zasady FIRST (Fast, Independent, Repeatable, Self-validating, Timely) oraz precyzyjny podział kodu każdego testu na sekcje (np. Arrange-Act-Assert). Przetestuj bota, przekazując mu poniższą deklarację oraz wymagania:

Cena bazowa biletu to 50 PLN. Dzieci poniżej 12 r.ż. mają 50% zniżki, seniorzy powyżej 65 r.ż. 30%. Klubowicze otrzymują dodatkowe 10% zniżki naliczane kaskadowo (zniżka nie jest naliczana od kwoty bazowej, ale od kwoty po zastosowaniu innych zniżek). Metoda rzuca wyjątek ValueError dla ujemnego wieku.

def calculate_ticket_price(age: int, is_club_member: bool) -> float:
    pass

Zadanie 2: Budowa bota odpowiedzialnego za tworzenie produkcyjnego kodu
Zbuduj drugiego Gema Python Developer, który na podstawie zwróconych testów z Zadania 1 przygotuje czysty, produkcyjny kod metody. W polu Instrukcje tego Gema kategorycznie zażądaj przestrzegania dobrych praktyk inżynierskich: zasad SOLID, prawa Demeter, reguł KISS (Keep It Simple, Stupid) i DRY (Don’t Repeat Yourself). Wygenerowany kod musi charakteryzować się najwyższą jakością. Skopiuj wygenerowany kod, uruchom go w lokalnym środowisku i solidnie przetestuj. Sprawdź, czy wszystkie testy zakończyły się powodzeniem.

Wskazówka: Wykorzystaj świeżo zbudowane Gemy do wygenerowania i weryfikacji testów dla logiki aplikacji, którą tworzyłeś w poprzednich laboratoriach (np. L#02: Framework unittest, L#04: Pokrycie kodu testami, L#06: Code Smells). To doskonała okazja, aby porównać kod testów napisany manualnie z rozwiązaniami od GenAI.

Klient API w środowisku Gemini Canvas

Gemini Canvas to zaawansowany edytor pozwalający na błyskawiczne prototypowanie, modyfikowanie i uruchamianie aplikacji webowych (np. lekkich klientów API) bezpośrednio z poziomu przeglądarki, bez potrzeby instalacji lokalnego IDE czy frameworków.

Zadania do wykonania

Zadanie 3: Prototypowanie klienta API
Zleć w Gemini (wykorzystując Canvas) zaprojektowanie nowoczesnego, przeglądarkowego narzędzia do testowania API. Aplikacja powinna pozwalać na wczytanie pliku ze specyfikacją testów (np. w formacie JSON, YAML lub CSV), zawierającego listę zapytań HTTP (URL, metoda, opcjonalny payload) oraz oczekiwane kody statusów. Narzędzie ma odczytać ten plik, wygenerować listę testów i umożliwić ich zbiorcze uruchomienie jednym przyciskiem. Całość powinna zamknąć się w jednym, czytelnym pliku integrującym HTML, CSS oraz JavaScript (wybór bibliotek UI pozostaw asystentowi). Zadbaj, aby interfejs czytelnie prezentował raport i statusy wykonanych testów. Taką aplikację możesz udostępnić w formie gotowego linku, a następnie dodać go do ulubionych zakładek w przeglądarce. W ten sposób zyskasz wygodny i szybki sposób na uruchomienie własnych testów z każdego miejsca na świecie.

Zadanie 4: Testy integracyjne na żywo
Uruchom aplikację za pomocą przycisku Preview w oknie Canvas. Przygotuj prosty plik ze specyfikacją (np. tests.json) dla darmowego serwera , w którym zdefiniujesz scenariusze dla różnych endpointów. Wczytaj plik do swojego nowego narzędzia, uruchom kolekcję jednym kliknięciem i zweryfikuj, czy klient poprawnie odczytał specyfikację, wykonał żądania oraz wygenerował czytelny raport z informacją o sukcesach i błędach.

Podsumowanie

Sztuczna inteligencja rewolucjonizuje szybkość budowania oprogramowania i automatyzacji, lecz to na inżynierze QA spoczywa obowiązek projektowania odpowiedniej architektury testów oraz krytycznej weryfikacji kodu. Pamiętaj o ryzyku zjawiska halucynacji modeli językowych. AI dostarcza tylko wysokiej jakości szkice, które zawsze wymagają audytu przez specjalistę przed wdrożeniem.

Testowanie i jakość oprogramowania

P#01: Asystent AI.

Asystent AI dla testera oprogramowania

Stwórz prostą aplikację z interfejsem użytkownika, która wykorzystuje API Gemini do wsparcia pracy testera oprogramowania. Skorzystaj z technologii Python, Flask, HTML, CSS i JavaScript. Ważne, aby aplikacja posiadała interfejs użytkownika.

Przykładowe tematy:

  • Asystent generujący testy jednostkowe na podstawie fragmentu kodu.
  • Narzędzie wykrywające naruszenia zasad SOLID lub prawa Demeter.
  • Asystent jakości kodu analizujący fragmenty i sugerujący poprawki.
  • Inteligentny generator przypadków testowych.
  • Aplikacja wspierająca dokumentowanie przypadków testowych.
  • Automatyczny recenzent kodu pod kątem typowych błędów i dobrych praktyk.
  • Asystent do analizy pokrycia kodu testami i sugerowania brakujących przypadków.

Wymagania

  • Projekt powinien posiadać prosty, estetyczny interfejs użytkownika.
  • Większość funkcjonalności powinna być realizowana przez LLM (np. Gemini) poprzez API. Użytkownik wykonuje minimum czynności, a interfejs oraz model zapewniają maksymalną automatyzację i wygodę.
  • W projekcie należy zastosować wyrafinowany prompt. Opisz w nim konkretnego agenta, np. Jestem ekspertem od testowania, analizuję kod pod kątem jakości oprogramowania, wykrywam typowe błędy i proponuję poprawki. Odpowiadam precyzyjnie, zwięźle i profesjonalnie…

Materiały pomocnicze

Wskazówki

  • Skup się na użyteczności i automatyzacji. Użytkownik powinien wykonywać jak najmniej kroków, a większość pracy powinna być realizowana przez aplikację i model LLM.
  • Wyeksponuj w interfejsie użytkownika możliwości agenta oraz jego specjalizację.
  • Dobra rada: Zadbaj o odpowiedni format odpowiedzi modelu LLM, aby interfejs użytkownika mógł wyświetlić ją w czytelny sposób.

Termin oddania projektu

15-06-2026 r. Strona główna

Technologia informacyjna

Kurs obejmuje praktyczne ćwiczenia z wykorzystania narzędzi Google Workspace w codziennym środowisku pracy i nauki. W trakcie zajęć studenci uczą się tworzenia dokumentów, arkuszy kalkulacyjnych, prezentacji oraz podstaw pracy z zasobami w chmurze.

Technologia informacyjna

Przedmiot obejmuje praktyczne ćwiczenia z wykorzystania narzędzi Google Workspace w codziennym środowisku pracy i nauki. W trakcie zajęć studenci uczą się tworzenia dokumentów, arkuszy kalkulacyjnych, prezentacji oraz podstaw pracy z zasobami w chmurze.

NrTematMateriały
L#01Wprowadzenie do Google DocsMateriały
L#02Google Workspace i GeminiMateriały
L#03Wprowadzenie do Google SheetsMateriały
L#04Arkusze kalkulacyjne w praktyceMateriały
L#05Tworzenie prezentacji w Google SlidesMateriały
L#06PodsumowanieMateriały

Technologia informacyjna

Laboratorium 1: Wprowadzenie do Google Docs.

Wprowadzenie

Google Docs to darmowy edytor tekstu online, który pozwala na tworzenie, edytowanie i współdzielenie dokumentów w czasie rzeczywistym. Wszystkie pliki są przechowywane w chmurze na Dysku Google, co zapewnia do nich dostęp z dowolnego urządzenia z połączeniem internetowym.

Cel laboratorium

Głównym celem zajęć jest zapoznanie się z edytorem Google Docs oraz poznanie mechanizmów jednoczesnej pracy wielu osób nad tym samym tekstem. Dowiesz się, jak udostępniać pliki oraz jak je poprawnie formatować, korzystając z dostępnych narzędzi i przygotowanych wskazówek.

Konto Google

Aby korzystać z Google Docs, załóż konto Google. Jest to konieczne, ponieważ wszystkie pliki są przechowywane w chmurze na Dysku Google, co zapewnia do nich dostęp z dowolnego urządzenia z połączeniem internetowym.

Praca zespołowa w Google Docs

Jedną z największych zalet Google Docs jest możliwość udostępniania dokumentów innym osobom i wspólnej edycji w czasie rzeczywistym. Oznacza to, że kilku użytkowników może pracować nad tym samym dokumentem jednocześnie, widząc wprowadzane zmiany na bieżąco. Dzięki temu Google Docs doskonale sprawdza się w pracy zespołowej, zwłaszcza podczas tworzenia notatek, raportów czy prac grupowych.

Proszę wpisać swoje dane na listę obecności.

Ćwiczenie 1: Praca w grupach

Proszę dobrać się w pary. Następnie jedna osoba z pary tworzy nowy dokument Google Docs (spójrz na film).

Następnie udostępnia go koledze / koleżance.

W kolejnym kroku proszę podać uprawnienia do edycji pliku podając adres e-mail kolegi / koleżanki z zespołu. Proszę wprowadzić do dokumentu (równolegle) swoje imiona i nazwiska.

Po wykonaniu ćwiczenia 1 kolejne zadania realizujemy już samodzielnie.

Ćwiczenie 2: Formatowanie tekstu

W udostępnionym pliku (strona 3) będą znajdowały się specjalne znaczniki, które pomogą Ci poprawnie sformatować dokument. Oto wskazówki, jak je interpretować:

  • W nawiasach klamrowych {} znajdują się komentarze — są to wskazówki dotyczące formatowania. Po wykonaniu zadania należy je usunąć.
  • {nagłówek 1 poziomu} oznacza, że dany fragment tekstu powinien być nagłówkiem pierwszego poziomu.
  • {dodaj odstęp} – w tym miejscu powinien znaleźć się dodatkowy odstęp między akapitami. Nie należy stosować ENTER do oddzielania akapitów – zamiast tego ustaw odpowiednie odstępy między nimi.
  • Akapity powinny być wyjustowane – oznacza to, że tekst powinien być równomiernie rozłożony na całej szerokości strony.
  • Odstępy między wierszami powinny wynosić 1,5 – ustaw taką wartość w opcjach formatowania tekstu.
  • *tekst* – oznacza, że dany tekst powinien być pogrubiony.
  • /tekst/ – oznacza, że dany tekst powinien być pochylony (kursywą).
  • {lista numerowana} – ten fragment powinien być zamieniony na listę numerowaną.
  • {lista wypunktowana} – ten fragment powinien być zamieniony na listę wypunktowaną.

Twoim zadaniem będzie poprawne sformatowanie tekstu zgodnie z powyższymi wskazówkami, a następnie usunięcie wszystkich {komentarzy}.

Otwórz dokument (strona 3) i skopiuj jego zawartość do nowego pliku. Następnie postępuj zgodnie z poniższym tutorialem.

Ćwiczenie 3: Samodzielna rozbudowa

Tym razem postaraj się samodzielnie sformatować dokument (strona 4 i 5). Zwróć uwagę na nowe elementy (wskazówki będą pomocne). W razie problemów poproś o pomoc prowadzącego zajęcia.

Nowe elementy w zadaniu:

  • Wstawianie obrazu: Menu → Wstaw → Obraz.
  • Tworzenie tabeli: Menu → Wstaw → Tabela (wybierz liczbę kolumn i wierszy).
  • Zmiana koloru tła komórki: Zaznacz komórki w tabeli; Menu → Formatuj → Tabela → Właściwości tabeli (Wybierz: Kolor / Kolor tła komórki).
  • Wstawianie spisu treści: Przejdź na początek dokumentu; Menu → Wstaw → Spis treści.
  • Dodanie wcięcia: Przejdź na początek akapitu; Menu → Formatuj → Wyrównanie i wcięcia (Zwiększ lub zmniejsz wcięcie).

Zadanie dodatkowe: Plan zajęć

Przygotuj harmonogram swoich zajęć w Google Docs, wzoruj się na oryginale udostępnionym przez AT Tarnów.

Wskazówki:

  • Ustaw orientację strony na poziomą.
  • Wstaw tabelę i uzupełnij ją.
  • Odpowiednio sformatuj dokument, dbając o czytelność i estetykę.
  • Wyróżnij wybrane komórki, jeśli uznasz to za stosowne.

Podsumowanie

Praca w chmurze z dokumentami tekstowymi to dzisiaj standard, który znacząco ułatwia przygotowywanie notatek czy wspólnych projektów. Umiejętność sprawnej edycji plików online oraz dbałość o ich estetykę przekładają się na profesjonalny wygląd raportów i prac grupowych. Dzięki tym kompetencjom Twoje dokumenty będą czytelne i odpowiednio uporządkowane.

Technologia informacyjna

Laboratorium 2: Google Workspace (Gemini, Keep i Forms).

Wprowadzenie

W dobie cyfrowej transformacji narzędzia chmurowe ułatwiają codzienne i zawodowe zadania. Integracja wszechstronnych rozwiązań pozwala na wygodniejszą edukację. Na szczególną uwagę zasługuje wsparcie sztucznej inteligencji (Google Gemini), intuicyjne budowanie formularzy czy ankiet (Google Forms) oraz efektywne zarządzanie informacjami przez cyfrowe notatki i zadania (Google Keep).

Cel laboratorium

Głównym celem zajęć jest praktyczne opanowanie i płynne posługiwanie się nowoczesnymi usługami z rodziny Google Workspace. W trakcie laboratorium wykorzystamy asystenta AI do szybkiego generowania i parafrazowania treści, utworzymy logiczny formularz do zbierania istotnych opinii, jak i zorganizujemy plan dnia za pomocą list do zrobienia (TO-DO). Wymienione umiejętności to kluczowe elementy nowoczesnej produktywności.

Organizacja plików

Zaloguj się na swoje konto Google, otwórz Google Drive (https://drive.google.com/) oraz uporządkuj swoje pliki. Postępuj zgodnie z poniższym filmikiem.

Generowanie treści w Google Gemini

Google Gemini to bardzo zaawansowany model językowy. Wyobraź sobie go jako inteligentnego asystenta, który potrafi: rozumieć i generować tekst, przetwarzać informacje, uczyć się i dostosowywać.

Otwórz Google Gemini (https://gemini.google.com/) oraz wpisz zapytanie (prompt). Skuteczny prompt powinien jasno określać rolę (personę), dokładne zadanie do wykonania, jego kontekst operacyjny oraz format wyjściowy. Skopiuj poniższą treść, a następnie wklej ją do chat’u Gemini:

Jesteś doświadczonym trenerem personalnym i ekspertem ds. zdrowia. Napisz krótki, motywujący artykuł o wpływie aktywności fizycznej na zdrowie. Tekst jest skierowany do początkujących studentów, którzy prowadzą w dużej mierze siedzący tryb życia i chcą zacząć ćwiczyć. Pisaną treść podziel na następujące sekcje: «Wpływ aktywności fizycznej na zdrowie», «Korzyści z siłowni», «Bieganie jako forma aktywności» i «Zalety pływania». Użyj również wypunktowań by uwypuklić zalety każdej z aktywności.

  • Persona — jaką rolę powinna przyjąć sztuczna inteligencja?
  • Zadanie — główne polecenie do wykonania.
  • Kontekst — dodatkowe szczegóły pomagające sprecyzować odbiorcę.
  • Wyjście — jak dokładnie ma wyglądać tekst końcowy.

Więcej wskazówek na temat tego, jak efektywnie konstruować zapytania, znajdziesz w oficjalnym przewodniku po promptach Google Workspace.

Skopiuj wygenerowany tekst i wklej go do nowego dokumentu Google Docs. Edytuj treść tak, aby miała dla Ciebie sens. Możesz zmienić przykłady, dodać swoje doświadczenia lub usunąć niepotrzebne fragmenty. Plik powinien posiadać odpowiednią nazwę: Wpływ aktywności fizycznej na zdrowie.

Formatowanie dokumentu

Sformatuj dokument według poniższych zasad:

  • Nagłówek 1: “Wpływ aktywności fizycznej na zdrowie”.
  • Nagłówek 2: “Korzyści z siłowni”.
  • Nagłówek 2: “Bieganie jako forma aktywności”.
  • Nagłówek 2: “Zalety pływania”.
  • Dodaj pogrubienie dla najważniejszych fragmentów tekstu.
  • Dodaj punktowaną listę przedstawiającą zalety każdej z aktywności.
  • Dodaj obrazek związany z aktywnością fizyczną (wygeneruj obrazek w Gemini, skorzystaj z narzędzia Utwórz obraz).

Zapisz dokument w folderze lab02.

Google Forms

Google Forms to bezpłatne narzędzie online, które umożliwia tworzenie profesjonalnych ankiet, testów, formularzy rejestracyjnych oraz innych interaktywnych kwestionariuszy. Dzięki intuicyjnemu interfejsowi użytkownika, nawet osoby bez specjalistycznej wiedzy technicznej mogą z łatwością projektować i rozpowszechniać formularze, a następnie analizować zebrane odpowiedzi.

Otwórz Google Forms (https://forms.google.com/) i utwórz nowy formularz zatytułowany Nawyki sportowe studentów - ankieta.

Dodaj następujące pytania:

  • Imię i nazwisko (Krótka odpowiedź: wymagane).
  • Jak często uprawiasz sport? (Jednokrotny wybór: codziennie, kilka razy w tygodniu, raz w tygodniu, rzadko).
  • Jaką formę aktywności wybierasz najczęściej? (Wielokrotny wybór: siłownia, bieganie, pływanie, sporty zespołowe, inne).
  • Ile czasu poświęcasz na trening? (Jednokrotny wybór: mniej niż 30 minut, 30-60 minut, więcej niż 60 minut)
  • Jak oceniasz swój poziom sprawności fizycznej? (Skala 1-5)

Udostępnij formularz koledze / koleżance w grupie. Następnie przeanalizuj wyniki.

Google Keep

Google Keep to cyfrowy notes, który pozwala szybko zapisywać myśli, tworzyć listy zadań, dodawać zdjęcia. Służy do organizacji codziennych spraw, przypominania o ważnych zadaniach i łatwego dostępu do notatek z dowolnego urządzenia.

Otwórz Google Keep oraz dodaj notatki.

Twoje zadanie będzie polegało na sporządzeniu odpowiednich notatek. Skopiuj poniższą treść do własnych notatek. Ustaw odpowiednie etykiety oraz tła dla notatek.

Notatka 1:

Tytuł: “Sportowe kino motywacji”

  • “Siła spokoju” - (Dramat, sportowy) - historia gimnastyka, który uczy się żyć tu i teraz.
  • “Najlepszy” - (Biograficzny, sportowy) - Oparty na faktach film o triathloniście Jerzym Górskim, który pokonuje własne słabości.
  • “Rydwany ognia” - (Dramat, sportowy) - Klasyczna opowieść o determinacji i dążeniu do celu.
  • “Wojownik” - (Dramat, sportowy) - Historia braci, którzy stają naprzeciwko siebie w turnieju MMA.
  • “Trener Carter” - (Dramat, sportowy) - O trenerze koszykówki, który uczy swoich podopiecznych nie tylko gry, ale i odpowiedzialności.
  • “Creed: Narodziny legendy” - (Dramat, sportowy) - Kontynuacja serii Rocky, o młodym bokserze, który szuka swojej drogi.
  • “Cud w Lake Placid” - (Dramat, sportowy) - Oparta na faktach historia hokejowej drużyny USA, która pokonuje faworytów z ZSRR.

Etykieta: Motywacja, Sport, Filmy (to są oddzielne etykiety!).

Powiadomienie: Sobota, 20:00.

Kolor tła: Pomarańczowy.

Notatka 2:

Tytuł: “Tygodniowy plan treningowy”

  • Poniedziałek: Bieganie 30 min (interwały), rozciąganie
  • Wtorek: Siłownia: nogi (przysiady, wykroki, martwy ciąg)
  • Środa: Pływanie 45 minut (style dowolne)
  • Czwartek: Odpoczynek, lekka joga
  • Piątek: Siłownia: klatka piersiowa, triceps
  • Sobota: Długie wybieganie (10 km)
  • Niedziela: Aktywny odpoczynek (spacer, rower)

Etykieta: Sport, Trening (to są oddzielne etykiety!).

Kolor tła: Zielony.

Notatka 3:

Tytuł: “Zdrowe posiłki na cały dzień”

  • Śniadanie: Owsianka z owocami (banan, jagody), orzechy
  • Obiad: Grillowany kurczak z brązowym ryżem i warzywami (brokuły, marchew)
  • Kolacja: Sałatka z tuńczykiem, awokado, pomidorem i ogórkiem
  • Przekąski: jabłko, jogurt naturalny
  • Nawodnienie: 2L wody

Etykieta: Dieta, Jedzenie, Zdrowie (to są oddzielne etykiety!).

Kolor tła: Niebieski.

Podsumowanie

Znajomość przydatnych narzędzi, takich jak Google Gemini, Google Forms czy Google Keep, po prostu ułatwia życie. Pomagają one szybciej komunikować się z innymi i uporządkować naszą cyfrową przestrzeń. Kiedy potrafisz sobie ułatwić i zautomatyzować pracę, sprawnie szukać informacji i efektywnie zbierać dane, wyrabiasz w sobie świetny nawyk. Dzięki niemu codzienna nauka lub praca stają się o wiele bardziej wydajne i przyjemniejsze.

Technologia informacyjna

Laboratorium 3: Wprowadzenie do Google Sheets.

Wprowadzenie

Google Sheets (Arkusze Google) to internetowy arkusz kalkulacyjny, umożliwiający tworzenie i analizę danych w tabelach. Działa w chmurze, umożliwiając współpracę wielu użytkowników w czasie rzeczywistym. Jest to darmowe narzędzie będące częścią pakietu Google Workspace, które łatwo integruje się z innymi aplikacjami.

Cel laboratorium

Celem zajęć jest zapoznanie się z aplikacją Google Sheets oraz opanowanie podstawowej analizy danych. Podczas pracy poznasz pojęcia arkusza, komórki i formuł, będziesz w stanie formatować dane, używać podstawowych funkcji do prostych kalkulacji oraz tworzyć wykresy, by podnieść czytelność prezentowanych parametrów.

Podstawowe pojęcia

Arkusz: Pojedyncza strona w pliku Google Sheets, składająca się z siatki wierszy i kolumn.

Wiersz: Poziomy układ komórek, oznaczony liczbami (1, 2, 3…).

Kolumna: Pionowy układ komórek, oznaczony literami (A, B, C…).

Komórka: Pojedynczy prostokąt, w którym znajdują się dane, oznaczony adresem (np. A1, B2).

Tutorial: Jak dodać nowy arkusz?

W lewym dolnym rogu ekranu znajduje się przycisk “+” (Dodaj arkusz).

Tutorial: Formatowanie warunkowe

To narzędzie, które pozwala automatycznie formatować komórki (np. zmieniać kolor tła lub tekstu) na podstawie określonych warunków. Przydaje się na przykład do oznaczania na zielono komórek z wynikami powyżej 2.0.

Tutorial: Format danych

Format danych pozwala określić, jak dane są wyświetlane w komórkach (np. jako liczby z dwoma miejscami po przecinku, daty w odpowiednim i oczekiwanym formacie lub waluty).

Tutorial: Formuły

Formuły to wyrażenia wykonujące obliczenia na danych w arkuszu. Formuła zawsze zaczyna się od znaku równości (=). Można używać wbudowanych funkcji (np. SUM()) oraz operatorów matematycznych (np. +, -, *, /).

Wstawienie:

=SUM(C3:C5)

Sumuje wartości w komórkach od C3 do C5.

Tutorial: Funkcja COUNTIF()

Funkcja COUNTIF() zlicza komórki w danym zakresie, które spełniają określone z góry kryteria.

Składnia:

COUNTIF(zakres; kryteria)

Przykład:

COUNTIF(C2:C5; ">2")

Zlicza, ile razy w zadanym zakresie od C2 do C5 wynik jest większy od 2.

Tutorial: Tworzenie wykresów

Zaznacz dane, które chcesz zaprezentować na wykresie. Kliknij Wstaw w górnym obszarze menu, a następnie wybierz Wykres. Później, w Edytorze wykresów po prawej stronie, po prostu wybierz typ odpowiadającego ci wykresu i dodatkowo dostosuj jego ogólny wygląd.

Tutorial: Funkcja IF()

Funkcja IF() zwraca jedną wartość, jeśli dany zadeklarowany warunek logiczny jest spełniony, oraz inną docelową wartość, jeśli ten nie jest spełniony.

Składnia:

IF(warunek; wartość_jeśli_prawda; wartość_jeśli_fałsz)

Przykład z życia:

=IF(C3>2; "Zal"; "Brak zal")

Jeżeli wartość wskazana w komórce C3 jest wyższa niż 2, nastąpi zwrócenie “Zal”, w przeciwnym razie wpisze po prostu “Brak zal”.

Zwróć uwagę, że wystarczy wprowadzić formułę do jednej komórki, a następnie przeciągnąć ją do pozostałych a formuła dostosuje się do każdej komórki.

Zadanie 1: Rekordy biegowe (wprowadzanie i edycja danych)

Dane: Lista 10 zawodników, ich imiona, nazwiska i czasy uzyskane w biegu na 100 metrów.

Imię;Nazwisko;Czas (sekundy)
Jan;Kowalski;10,5
Anna;Nowak;11,2
Piotr;Wiśniewski;10,8
Maria;Dąbrowska;11,5
Andrzej;Lewandowski;10,9
Katarzyna;Wójcik;11,1
Tomasz;Kamiński;10,7
Magdalena;Kowalczyk;11,4
Marek;Zieliński;11,0
Ewa;Szymańska;11,3

Polecenie: Utwórz nowy arkusz i wprowadź dane do nowego arkusza. Użyj klawiszy Enter (przenosi do następnego wiersza), Tab (przenosi do następnej kolumny) i F2 (edytuj komórkę) do nawigacji i edycji danych.

Zadanie 2: Analiza wyników skoku w dal (formatowanie danych)

Dane: Wyniki 15 zawodników w skoku w dal (w metrach).

Imię;Nazwisko;Wynik (metry)
Jan;Kowalski;6,85
Anna;Nowak;7,12
Piotr;Wiśniewski;6,98
Maria;Dąbrowska;7,25
Andrzej;Lewandowski;6,78
Katarzyna;Wójcik;7,05
Tomasz;Kamiński;7,30
Magdalena;Kowalczyk;6,92
Marek;Zieliński;7,18
Ewa;Szymańska;7,20
Krzysztof;Jankowski;6,88
Alicja;Mazur;7,00
Paweł;Krawczyk;7,35
Beata;Gajewska;6,95
Adam;Rutkowski;7,22

Polecenie: Utwórz nowy arkusz i wprowadź dane. Sformatuj komórki, aby wyświetlały wyniki z dokładnością do dwóch miejsc po przecinku. Zastosuj formatowanie warunkowe, aby wyróżnić wyniki powyżej 7 metrów.

Zadanie 3: Obliczanie BMI (podstawowe funkcje)

Dane: Lista 20 osób, ich waga (w kilogramach) i wzrost (w metrach).

Imię;Nazwisko;Waga (kg);Wzrost (m)
Jan;Kowalski;80;1,80
Anna;Nowak;65;1,65
Piotr;Wiśniewski;90;1,85
Maria;Dąbrowska;70;1,70
Andrzej;Lewandowski;85;1,90
Katarzyna;Wójcik;60;1,60
Tomasz;Kamiński;75;1,75
Magdalena;Kowalczyk;68;1,68
Marek;Zieliński;95;1,95
Ewa;Szymańska;72;1,72
Krzysztof;Jankowski;88;1,88
Alicja;Mazur;63;1,63
Paweł;Krawczyk;92;1,92
Beata;Gajewska;67;1,67
Adam;Rutkowski;82;1,82
Karolina;Sokołowska;58;1,58
Rafał;Pawlak;98;1,98
Agata;Lis;78;1,78
Michał;Woźniak;83;1,83
Sylwia;Kozłowska;69;1,69

Polecenie: Utwórz nowy arkusz i wprowadź dane. Użyj formuły do obliczenia BMI dla każdej osoby na podstawie wzoru: waga / wzrost². Zastosuj formatowanie do wyświetlania wyników z dokładnością do 2 miejsc po przecinku.

Podsumowanie

Google Sheets to narzędzie, które pozwala na organizację danych, obliczenia i wizualizację wyników. Dzięki prostym funkcjom i automatycznym formułom łatwo przygotować raporty, zestawienia i analizy nawet bez specjalistycznej wiedzy technicznej.

Technologia informacyjna

Laboratorium 4: Google Sheets.

Wprowadzenie

Praca nauczyciela WF, trenera czy organizatora zawodów to nie tylko bezpośredni kontakt z zawodnikami, ale też mnóstwo “papierkowej” roboty. Google Sheets to Twój osobisty, wirtualny asystent, który automatycznie przeliczy stawki za treningi personalne, błyskawicznie wskaże najszybszego sprintera w klasie i wyłoni zwycięzców turnieju piłkarskiego. Narzędzia informatyczne oszczędzają Twój czas, pozwalając Ci skupić się na tym, co najważniejsze — na sporcie.

Cel laboratorium

Dowiesz się, jak zautomatyzować codzienną pracę trenera i organizatora zawodów. Nauczysz się blokować komórki w formułach (adresacja bezwzględna). Przećwiczysz sortowanie i filtrowanie list zawodników. Zbudujesz powiązane ze sobą arkusze wyników.

Zadanie 1: Karta pracy trenera personalnego

Jako trener personalny, musisz sprawnie zarządzać rozliczeniami ze swoimi podopiecznymi. Obecnie prowadzisz 3 stałych klientów, z których każdy trenuje w innym trybie: jeden codziennie, drugi raz w tygodniu, a trzeci wpada na salę sporadycznie.

Przygotuj arkusz w taki sposób, aby każdy klient posiadał swoją własną sekcję składającą się z dwóch kolumn: daty treningu oraz liczby przepracowanych godzin. W efekcie Twój arkusz będzie posiadał 6 kolumn z danymi (np. kolumna A — data, kolumna B — godziny dla pierwszego klienta, kolumna C — data, kolumna D — godziny dla drugiego klienta itd.).

W pracy trenera lista danych ciągle rośnie. Zamiast co chwilę poprawiać formuły (np. zmieniać SUMA(A2:A10) na SUMA(A2:A100)), Google Sheets pozwala na stosowanie tzw. zakresów otwartych. Zapis A2:A (bez cyfry na końcu) oznacza: “weź wszystko od drugiego wiersza aż do samego dołu arkusza”.

Przygotuj trzy oddzielne podsumowania kosztów (po jednym dla każdego klienta). Wykorzystaj mechanizm zakresów otwartych (np. =SUMA(B3:B) * 100), aby Twoje formuły automatycznie doliczały każdą nową sesję wpisaną do arkusza w przyszłości. Pozwoli Ci to na prowadzenie rozliczeń “w nieskończoność” bez żadnych poprawek w strukturze pliku.

Oto przykładowy rezultat. Pamiętaj, że wprowadzenie nowych danych powinno automatycznie aktualizować podsumowania.

Zadanie 2: Tabela skoczków narciarskich

Podczas zawodów w skokach narciarskich gromadzisz dziesiątki pomiarów. Przeanalizowanie ich “na oko” i ręczne szukanie lidera bywa uciążliwe i sprzyja pomyłkom. Twoim zadaniem jest przepisanie poniższych danych do arkusza. Zrób to dokładnie w takiej kolejności, w jakiej są podane (dane są celowo nieposortowane).

Zawodnik;Kraj;Skok 1 [m];Skok 2 [m];Nota końcowa
Ryoyu Kobayashi;JPN;138,5;134,0;282,1
Stefan Kraft;AUT;139,0;140,0;310,5
Anze Lanisek;SLO;132,5;131,0;265,4
Andreas Wellinger;GER;135,0;136,5;290,8
Jan Hoerl;AUT;128,0;132,0;255,2
Pius Paschke;GER;125,5;129,5;248,9
Karl Geiger;GER;131,0;130,5;268,2
Marius Lindvik;NOR;134,5;133,0;275,6
Gregor Deschwanden;SUI;127,0;128,5;240,1
Peter Prevc;SLO;130,0;132,5;262,3
Timi Zajc;SLO;126,0;124,5;235,8
Lovro Kos;SLO;133,0;134,5;278,9
Johann Andre Forfang;NOR;132,0;129,0;259,4
Manuel Fettner;AUT;129,5;131,5;260,7
Daniel Tschofenig;AUT;124,0;127,0;230,5
Kamil Stoch;POL;126,5;125,0;238,2
Piotr Żyła;POL;123,5;128,0;232,1
Dawid Kubacki;POL;121,0;122,5;220,4
Halvor Egner Granerud;NOR;118,5;120,0;215,7
Aleksander Zniszczoł;POL;122,0;125,5;228,9

Po wprowadzeniu wszystkich 20 wierszy, zamień te dane w profesjonalną bazę! Zaznacz obszar z wartościami i z górnego menu wybierz opcję Formatuj → Przekonwertuj na tabelę.

Następnie wykorzystaj funkcję sortowania tabeli, aby uszeregować zawodników według noty końcowej (od największej do najmniejszej).

Podpowiedź: Aby to zrobić, kliknij małą ikonę strzałki (filtrowania) w nagłówku kolumny “Nota końcowa” i wybierz opcję Sortuj Z-A. Dzięki temu od razu zweryfikujesz wyniki i zobaczysz, kto stanął na podium. Na koniec, pod stworzoną tabelą, wypisz ręcznie imiona i nazwiska trzech najlepszych skoczków tych zawodów.

Oto przykładowy rezultat:

Zadanie 3: Wyniki biegu na 60m

Na lekcji WF sprawdzasz czasy swoich uczniów w sprincie na 60 metrów. Chcesz szybko obliczyć i pokazać młodzieży, ile sekund stracili do najszybszego zawodnika. Aby zrobić to sprawnie, musisz zrozumieć mechanizm blokowania komórek, czyli różnicę między adresacją względną a bezwzględną.

Wyobraź sobie, że symbol dolara ($) to solidna kłódka. To, co stoi bezpośrednio po nim, zostaje “zamrożone” i nie zmienia się podczas kopiowania formuły:

  • A1Pełna swoboda: Przeciągasz w dół? Zmienia się wiersz (A2, A3…). Przeciągasz w bok? Zmienia się kolumna (B1, C1…).
  • $A1Zablokowana kolumna: Zawsze będziemy patrzeć na kolumnę A, ale wiersze będą się zmieniać przy przeciąganiu w dół.
  • A$1Zablokowany wiersz: Zawsze będziemy patrzeć na 1. wiersz, ale kolumny mogą się zmieniać przy przeciąganiu w bok.
  • $A$1Pełna blokada (adresacja bezwzględna): Komórka jest całkowicie zamrożona. Niezależnie gdzie przeciągniesz formułę, ona zawsze będzie brała wartość z tego samego miejsca.

Eksperymenty przygotowawcze (wykonaj w nowym arkuszu):

  1. Wprowadź czasy zawodników w komórkach od A2 do A8.
  2. W komórce B2 wpisz formułę obliczającą różnicę w czasie względem najlepszego wyniku.
  3. Wykorzystaj odwołanie bezwzględne do komórki z najlepszym czasem.
  4. Przeciągnij formułę w dół i sprawdź poprawność wyników.

Podsumowanie

Google Sheets jest przydatnym narzędziem do automatyzacji obliczeń, analizy danych, budowania tabel i zarządzania wynikami. Umożliwia oszczędność czasu oraz sprawniejszą pracę z informacjami w praktyce szkolnej i zawodowej.

Technologia informacyjna

Laboratorium 5: Google Slides.

Wprowadzenie

Umiejętność przejrzystego i estetycznego prezentowania wiedzy jest kluczowa w dzisiejszym świecie. Google Slides to intuicyjne i potężne narzędzie, które pozwala na szybkie tworzenie atrakcyjnych wizualnie prezentacji.

Cel laboratorium

Celem zajęć jest zapoznanie się z narzędziem Google Slides poprzez stworzenie własnej prezentacji tematycznej. Dodatkowo utrwalisz wiedzę z Google Sheets, w szczególności w zakresie wykorzystania formuły JEŻELI (IF) do przetwarzania wyników sportowych.

Zadanie 1: Projekt systemu turniejowego

Zanim rozpoczniesz pracę z prezentacją, powtórzmy jedną z użytecznych formuł: JEŻELI (ang. IF). Pozwala ona na wykonanie testu logicznego i zwrócenie jednej z dwóch wartości (w zależności od tego czy test jest prawdziwy lub fałszywy).

Składnia formuły:

=JEŻELI(test_logiczny; wartość_jeśli_prawda; wartość_jeśli_fałsz)

Na przykład poniższa formuła sprawdzi, czy wynik w komórce A1 jest większy niż w B1. Jeżeli rezultat testu będzie prawdziwy, to w komórce wyświetli się “Wygrana”, w przeciwnym wypadku “Przegrana”.

=JEŻELI(A1>B1; "Wygrana"; "Przegrana")

Skopiuj arkusz Google Sheets - MŚ 1998 i wybierz Plik -> Utwórz kopię.

Twoim zadaniem będzie uzupełnienie grup mistrzostw świata oraz faz play-off w piłce nożnej. Skorzystaj z gotowych formuł w dokumencie.

Fazy play-off (zakładki w arkuszu) należy wypełnić w taki sposób, aby drużyny wyświetlały się dynamicznie w zależności od wyników z poprzednich meczów. Wyniki drużyn znajdziesz na Wikipedii.

Zadanie 2: Tańce sportowe

Google Slides to narzędzie do tworzenia prezentacji online. W ramach drugiego zadania stworzysz prezentację na temat tańców sportowych. Prezentacja powinna zawierać opisy i zdjęcia najpopularniejszych tańców, takich jak: walc angielski (standardowy), tango (standardowy), walc wiedeński (standardowy), foxtrot (standardowy), samba (latynoamerykański), cha-cha (latynoamerykański), rumba (latynoamerykański), jive (latynoamerykański).

Zadbaj o to, aby prezentacja była estetyczna i przejrzysta. Możesz skorzystać z gotowych szablonów dostępnych w Google Slides. Zanim rozpoczniesz pracę, zapoznaj się z interfejsem aplikacji, po czym utwórz nową prezentację i dodaj odpowiednie slajdy.

Przejdź do Google Slides, kliknij znak “+” w lewym górnym rogu, aby utworzyć nową prezentację i dodaj odpowiednie slajdy.

Możesz wzorować się na przykładowej prezentacji, którą wstępnie przygotowałem: Tańce sportowe (PDF).

Jeśli masz problem z dodawaniem slajdów, skorzystaj z poniższego filmu instruktażowego:

Podsumowanie

Potrafisz wykorzystać w praktyce formułę JEŻELI oraz stworzyć estetyczną prezentację multimedialną w Google Slides.

Technologia informacyjna

Laboratorium 6: Podsumowanie.

Wprowadzenie

Po kilku tygodniach pracy z pakietem Google Workspace nadszedł czas na uporządkowanie zdobytej wiedzy i przygotowanie się do kolokwium zaliczeniowego. Dotychczasowe laboratoria obejmowały pracę z narzędziami Google Docs, Gemini, Keep, Forms, Sheets oraz Slides.

Cel

Celem tego laboratorium jest uporządkowanie materiałów na Dysku Google oraz przygotowanie się do kolokwium zaliczeniowego podsumowującego dotychczasową pracę z pakietem Google Workspace.

Przygotowanie do kolokwium

W ramach przygotowań do kolokwium zaliczeniowego z Technologii Informacyjnej, podsumowującego dotychczasową pracę z pakietem Google Workspace (Google Docs, Gemini, Keep, Forms, Sheets, Slides), należy uporządkować swoje materiały na Dysku Google.

Porządkowanie zasobów na Dysku Google

Przed przystąpieniem do kolokwium, proszę o zorganizowanie plików na swoim Dysku Google w następujący sposób:

  • Na swoim Dysku Google należy utworzyć główny katalog o nazwie: ti_[imię]_[nazwisko] (np. ti_tomasz_gądek).
  • Wewnątrz głównego katalogu należy utworzyć sześć podkatalogów o nazwach: lab01lab06.
  • Wszystkie ukończone ćwiczenia z poszczególnych laboratoriów należy przenieść do odpowiednich katalogów.
  • Należy upewnić się, że wszystkie ćwiczenia są kompletne i gotowe do weryfikacji. Zawartość tych katalogów będzie sprawdzana podczas kolokwium.

Przykładowe kolokwium

Zadanie 1: Tabela rekordzistów na 100m

W Google Docs należy stworzyć tabelę prezentującą aktualnych rekordzistów świata w biegu na 100 metrów mężczyzn i kobiet. Wzoruj się na tabelach dostępnych na stronie Bieg na 100 metrów (z pominięciem flag). Należy również utworzyć hiperłącza tak, aby kliknięcie w nazwę zawodnika lub w nazwę miejsca zawodów przenosiło do odpowiedniej strony internetowej.

Zadanie 2: Tabliczka mnożenia

W Google Sheets należy wygenerować tabliczkę mnożenia od 1 do 100. W komórkach od B1 do K1 oraz od A2 do A11 należy wprowadzić liczby od 1 do 10. Następnie, w komórce B2 należy wprowadzić odpowiednią formułę wykorzystującą adresowanie mieszane. Nie należy wprowadzać żadnych wartości ani formuł w pozostałych komórkach przed wykonaniem przeciągnięcia. Przeciągnięcie komórki B2 w prawo i w dół powinno spowodować automatyczne wypełnienie całej tabliczki mnożenia.

Powodzenia na kolokwium 😉

Podsumowanie

Laboratoria z Technologii Informacyjnej pozwoliły zapoznać się z kluczowymi narzędziami pakietu Google Workspace. Umiejętność sprawnego korzystania z Google Docs, Sheets i Slides stanowi solidną podstawę do efektywnej pracy z dokumentami, danymi i prezentacjami w środowisku cyfrowym.

Laboratorium dyplomowe

Przedmiot obejmuje przygotowanie projektu dyplomowego, wytyczne formalne, zasady organizacji pracy oraz materiały pomocnicze do realizacji pracy dyplomowej.

Laboratorium dyplomowe

Przedmiot obejmuje przygotowanie projektu dyplomowego, wytyczne formalne, zasady organizacji pracy oraz materiały pomocnicze do realizacji pracy dyplomowej.

NrTematMateriały
L#01Laboratorium dyplomowePDF
L#02Wskazówki dla autorów prac dyplomowych - StrukturaMateriały
L#03Wskazówki dla autorów prac dyplomowych - FormatowanieMateriały
L#04Zrealizowane prace inżynierskieMateriały
L#05Regulamin dyplomowania oraz wymagane wzory dokumentówMateriały

Wskazówki dla autorów prac dyplomowych

Temat: Zebrane informacje na temat układu merytorycznego i struktury pracy dyplomowej.

Wprowadzenie

Pisanie pracy dyplomowej to proces, który wymaga nie tylko wiedzy merytorycznej, ale również odpowiedniej organizacji układu pracy i przestrzegania ustalonych wytycznych dotyczących jej struktury.

Cel

Przedstawione poniżej wskazówki mają na celu ujednolicenie struktury i formy prac inżynierskich realizowanych w Katedrze Informatyki.

Struktura pracy dyplomowej

Poniżej przedstawiono poszczególne elementy, które powinna zawierać praca dyplomowa, wraz z krótkim opisem ich charakteru.

Karta tytułowa

Powinna być zgodna z zaleceniami z Dziekanatu.

Spis treści

Spis poszczególnych części z odniesieniami do stron. Zwracać uwagę na jego aktualizowanie podczas nanoszenia poprawek w pracy.

Uwagi wstępne

Powinny zawierać opis celu, przedmiotu i zakresu pracy oraz krótko informować, co jest omówione w poszczególnych rozdziałach. Objętość tego rozdziału to około 2–3 strony.

Część teoretyczno-opisowa

W przypadku prac praktyczno-aplikacyjnych powinna zawierać krótki opis sprzętu i oprogramowania użytego do realizacji pracy z uwypukleniem zagadnień ważnych podczas realizacji pracy.

UWAGA! W tej części proszę nie przepisywać dokumentacji technicznej!

W przypadku pracy zawierającej elementy teoretyczne oraz aplikacyjne, należy podać odpowiednie informacje dla obu tych części.

UWAGA! Podczas pisania tej części (obojętnie, czy praktycznej, czy teoretycznej) bezwzględnie należy podawać cytowania do literatury, z której się korzysta!

Sposób powoływania się wewnątrz tekstu zależy od przyjętego formatu budowy bibliografii na końcu pracy. Najlepiej stosować formę wplecioną między zdania:

[nr pozycji w spisie] lub Autor (rok wydania pracy)

Sugerowana objętość tej części to około 15–25 stron.

Opis realizacji zadania postawionego w pracy

Jest to najważniejsza część pracy, gdyż zawiera opis tego, co dyplomant wykonał podczas jej realizacji. Należy tu podać dokładny opis postawionego zadania i prowadzonych działań. Szczegóły są zależne od konkretnego tematu.

Obszerne i nieco mniej istotne części opisu realizacji zadania, które mogłyby pogarszać czytelność rozdziału, takie jak np. duże fragmenty kodów źródłowych oprogramowania, twierdzenia niezwiązane bezpośrednio z pracą itp., można umieścić w dodatkach z odpowiednią adnotacją w głównej części pracy.

Objętość tej części pracy nie może być mniejsza niż objętość części opisowej.

Testy poprawności realizacji zadania

W tej części należy zawrzeć opis prowadzonych badań testowych sprawdzających poprawność realizacji zadania. Mogą tu znaleźć się np. wyniki testów oprogramowania czy udokumentowana poprawność działania aplikacji.

Objętość tej części to około 10–15 stron.

Uwagi końcowe

Powinny zawierać podsumowanie i wnioski, jakie nasunęły się po zakończeniu realizacji pracy. Przykładowo, można tu opisać, co udało się zrealizować, z czym były największe trudności, do czego i dlaczego nie udało się dotrzeć itp. Często wskazuje się w tym miejscu sugerowane kierunki dalszego rozwoju zagadnień poruszonych na łamach pracy.

Objętość: około 2–4 strony.

Bibliografia

Musi zawierać alfabetyczny (według nazwisk Autorów) spis pozycji źródłowych użytych do przygotowania pracy. Pozycje, przy których nie da się jednoznacznie wskazać Autorów (np. dokumentacja sprzętu i oprogramowania czy niektóre linki do stron internetowych), należy podać na końcu w kolejności alfabetycznej według tytułów.

Należy obierać jeden z dwóch formatów stylizacji spisu literatury (i stosować go konsekwentnie):

Format 1: [nr pozycji] Autor, Tytuł, dane bibliograficzne.

Format 2: Autor (rok wydania), Tytuł, dane bibliograficzne.

Minimalna liczba pozycji w bibliografii to około 6–7. Maksymalna, co do zasady, pozostaje bez ograniczeń.

Dodatki

Stanowią część opcjonalną na załączniki, kody źródłowe oraz obszerną dokumentację zewnętrzną.

Podsumowanie

Stosowanie się do zaproponowanych reguł pozwoli Ci w łatwy i spójny sposób zaprojektować strukturę pracy dyplomowej. Przejrzyste formatowanie, dbałość o detale i zachowanie rzetelnej metodyki w procesie dokumentacji mają kolosalne znaczenie dla finalnej oceny Twojej pracy. Pamiętaj – to Ty jesteś odpowiedzialny za prezentację swoich wyników!

Wskazówki dla autorów prac dyplomowych

Temat: Zebrane informacje na temat wymogów edytorskich i formatowania tekstu w pracy dyplomowej.

Wprowadzenie

Pisanie pracy dyplomowej to proces, który wymaga nie tylko wiedzy merytorycznej, ale również odpowiedniej organizacji i przestrzegania ustalonych wytycznych edytorskich.

Cel

Celem tych zaleceń jest dostarczenie dyplomantom kompleksowego standardu dotyczącego formatowania tekstu, tworzenia spisu treści, bibliografii, a także wstawiania rysunków, tabel i wzorów matematycznych. Przestrzeganie tych wskazówek gwarantuje, że Twoja praca będzie czytelna, profesjonalna i zgodna z wymogami uczelni.

Wymogi edytorskie i formatowanie

Poniżej przedstawiono zasady formatowania tekstu, umieszczania wzorów, tabel i rysunków w pracy dyplomowej.

Czcionka i odstępy

Cały tekst pracy należy pisać czcionką Times New Roman w rozmiarze 12. Odstępy pomiędzy wierszami – 1,5. W tabelach można stosować mniejszy rozmiar czcionki (jeśli np. ułatwi to zmieszczenie tabeli na stronie). Pomiędzy akapitami należy zostawiać 1 pusty wiersz. Tytuły rozdziałów i podrozdziałów pogrubione.

Wzory matematyczne

Przed i po wzorze należy zostawić jeden pusty wiersz. Sam wzór ma być wycentrowany. Jeżeli jest na niego powołanie w tekście, to musi on posiadać numer, zapisany w nawiasie okrągłym i dosunięty do prawego marginesu.

Format numeru według wytycznych zapisany w nawiasach okrągłych:

( nr dużego rozdziału . nr wzoru w tym rozdziale )

Powołanie na wzór w tekście ma zawierać odniesienie do odpowiedniego numeru. Należy unikać zwrotów takich jak w poniższym wzorze…, ponieważ po dodaniu nowych tekstów układ strony może się przesunąć.

Rysunki

W tekście pracy jako rysunki należy traktować i tym samym stylem opisywać również:

  • diagramy,
  • wykresy,
  • schematy blokowe,
  • fotografie,
  • okna programów (zrzuty UI),
  • wszelkie inne obiekty graficzne.

Przed rysunkiem należy zostawić jeden pusty wiersz. Rysunek oraz jego podpis powinny być umieszczone symetrycznie na środku strony (wyśrodkowane).

Poprawna składnia formatu podpisu pod grafiką:

Rys. nr dużego rozdziału.nr rysunku w tym rozdziale. Tytuł rysunku.

Za podpisem rysunku należy również zostawić pusty wiersz. Podobnie jak przy wzorach, nie należy stosować zwrotów wskazujących położenie: np. na poniższym rysunku…, lecz powoływać się bezpośrednio na jego numer.

Tabele

Przed podpisem tabeli zostawiamy jeden pusty wiersz. Podpis zawsze umieszczamy przed (nad) tabelą. Można go dosunąć do lewego marginesu - i opcjonalnie lekko podkreślić.

Poprawna składnia formatu podpisu tabeli to:

Tabela nr dużego rozdziału.nr tabeli w tym rozdziale. Tytuł tabeli.

Bezpośrednio po tabeli także zostawiamy jeden pusty wiersz. Jak w przypadku rysunków, unikaj zwrotów w stylu na poniższej tabeli. Odwołuj się do danych powołując się w tekście jednoznacznie na konkretny numer tabeli.

Numeracja stron

Strony należy numerować, sugerowane miejsce na numery: na dole na środku.

Nagłówek i stopka

Mogą być zdefiniowane zgodnie z upodobaniami, ale jest to element opcjonalny, nie powinny one zaburzać czytelności strony.

Marginesy

Powinny umożliwiać oprawę lub zbindowanie pracy.

Podsumowanie

Stosowanie się do zaproponowanych reguł pozwoli Ci w łatwy i spójny sposób zaprojektować strukturę pracy dyplomowej. Przejrzyste formatowanie, dbałość o detale i zachowanie rzetelnej metodyki w procesie dokumentacji mają kolosalne znaczenie dla finalnej oceny Twojej pracy. Pamiętaj – to Ty jesteś odpowiedzialny za prezentację swoich wyników!

Zrealizowane prace inżynierskie

Najnowsze prace dyplomowe pierwsze.

RokDataTytułMateriały
202616.04.2026Projekt i implementacja gry typu Tower DefensePDF
202616.04.2026Projekt i implementacja gry komputerowej z dynamicznym systemem walki opartym o muzykęPDF
202616.04.2026Projekt i implementacja programu narzędziowego do testowania API aplikacji webowychPDF
202613.03.2026Projekt i implementacja gry strategicznej z systemem zarządzania zasobami i ekwipunkiemPDF
202620.02.2026Projekt i implementacja aplikacji webowej do zarządzania osobistymi kolekcjami multimediówPDF
202606.02.2026Projekt i implementacja gry z elementami przetrwania i rozwoju postaciPDF
202606.02.2026Projekt i implementacja aplikacji mobilnej wspomagającej planowanie treningu siłowegoPDF
202606.02.2026Projekt i implementacja interaktywnej platformy edukacyjnej z mechanizmami weryfikacji postępówPDF
202606.02.2026Projekt i implementacja aplikacji mobilnej do wymiany żywnościPDF
202514.02.2025Projekt i implementacja gry survivalowejPDF
202514.02.2025Projekt i implementacja systemu do rozliczania wydatków grupowychPDF
202514.02.2025Gra wyścigowa z przeszkodamiPDF
202514.02.2025Aplikacja do zamawiania posiłkówPDF
202514.02.2025Projekt i implementacja aplikacji webowej wspomagającej opiekę nad zwierzętami domowymiPDF
202514.02.2025Aplikacja prozdrowotnaPDF
202512.02.2025Projekt i implementacja forum dyskusyjnegoPDF
202512.02.2025Projekt i implementacja gry przygodowejPDF
202512.02.2025Projekt i implementacja aplikacji webowej do zarządzania rezerwacjami wizyt w salonie fryzjerskimPDF
202512.02.2025Projekt i implementacja aplikacji webowej do zarządzania pojazdamiPDF
202421.02.2024Projekt i implementacja aplikacji webowej umożliwiającej publikowanie i przeglądanie ogłoszeń z lokalami do wynajęciaPDF
202421.02.2024Projektowanie i implementacja aplikacji internetowej wspomagającej efektywne zarządzanie czasem i zadaniamiPDF
202421.02.2024Aplikacja webowa do zakupów artykułów spożywczychPDF
202421.02.2024Asystent dietetycznyPDF
202421.02.2024Aplikacja do nauki języków obcychPDF
202421.02.2024Testowanie kodu z wykorzystaniem frameworka SpockPDF
202421.02.2024Aplikacja do zarządzania grafikami pracy w firmiePDF
202415.02.2024Analiza wydajności wybranych najpopularniejszych języków programowaniaPDF
202409.02.2024Testowanie kodu z wykorzystaniem frameworka JUnitPDF
202409.02.2024System zarządzania zasobami żywnościowymi oraz dietąPDF
202328.04.2023Projekt oraz implementacja komunikatora internetowegoPDF
202304.04.2023Kino samoobsługowePDF
202331.03.2023Aplikacja do zarządzania zawodnikami międzynarodowej federacji wspinaczki sportowej (IFSC)PDF
202229.09.2022Oprogramowanie do bezpiecznego zarządzania hasłami oraz poufnymi danymiPDF
202224.02.2022Aplikacja do rezerwacji wizyt pacjentów w gabinecie fizjoterapiiPDF
202224.02.2022Elektroniczny trener personalny — Iron MusclePDF
202224.02.2022Elektroniczny second handPDF

Projektowanie interfejsów użytkownika

Kurs obejmuje projektowanie responsywnych interfejsów użytkownika, pracę nad strukturą aplikacji oraz przygotowanie projektu z uwzględnieniem wymagań funkcjonalnych i wizualnych.

Projektowanie interfejsów użytkownika

Przedmiot obejmuje praktyczne przygotowanie responsywnego interfejsu użytkownika zgodnie z wymaganiami określonymi w projekcie. W tym module dostępny jest wyłącznie projekt.

NrTematMateriały
P#01Wymagania dotyczące projektuProjekt

Projektowanie interfejsów użytkownika

P#01: Wymagania.

Wprowadzenie

Poniższy dokument przedstawia wymagania dotyczące realizacji projektu z przedmiotu Projektowanie Interfejsów Użytkownika. Projekt polega na stworzeniu responsywnego interfejsu, składającego się z minimum pięciu podstron, opartych o technologie HTML, CSS i JavaScript.

Cel

Głównym celem projektu jest praktyczne zastosowanie wiedzy nabytej podczas zajęć poprzez samodzielne skonstruowanie nowoczesnego, estetycznego i spójnego interfejsu. Projekt sprawdza umiejętności dotyczące tworzenia responsywnych układów oraz wykorzystania zewnętrznego API.

Etapy realizacji

Projekt jest podzielony na trzy etapy.

Etap/TerminOpis
Mockupy. Do 15 kwietnia.Opracowanie makiet w programie dedykowanym (np. Figma, Balsamiq) dla wersji desktop, tablet i mobile.
Implementacja. Do 15 maja.Implementacja interfejsu użytkownika, wykorzystanie API, przygotowanie responsywności.
Dokumentacja i testy. Do 15 czerwca.Przygotowanie dokumentacji w Markdown, testy aplikacji w przeglądarkach (Chrome, Edge, Safari, Firefox, Opera) na trzech rozdzielczościach.

Uwaga: Niedotrzymanie terminów skutkuje obniżeniem oceny końcowej o 1 stopień.

Wymagania dla poszczególnych widoków

Aplikacja powinna składać się z minimum pięciu podstron. Każda podstrona powinna zawierać menu, treść i stopkę.

Widok/PodstronaWymagania funkcjonalne i wizualne
Strona głównaPowinna zawierać logo, menu nawigacyjne, stopkę oraz krótki opis.
Lista danychWyświetlanie listy elementów. Możliwość paginacji / sortowania / filtrowania wyników. Różne układy listy w zależności od ekranu (np. tabela na desktopie, karty na mobile). Dane można pobrać z publicznego API (np. JSONPlaceholder).
SzczegółyWidok pojedynczego elementu (np. użytkownik, post, produkt). Dynamiczne pobieranie szczegółowych danych po kliknięciu na element listy. Przyciski Wróć i Edytuj (jeśli aplikacja to umożliwi).
Podstrona z 3 kolumnamiDesktop: 3 kolumny obok siebie. Tablet: 2 kolumny + 1 poniżej. Mobile: układ jednokolumnowy. Zawartość powinna mieć konsekwentny układ i spójne nagłówki.
Dodatkowa podstronaMoże zawierać np. formularz kontaktowy, galerię zdjęć.

Responsywność

Projekt musi być w pełni responsywny.

  • Desktop: [szerokość] ≥ 1024px
  • Tablet : [szerokość] ≥ 768px i [szerokość] ≤ 1023px
  • Mobile : [szerokośc] ≤ 767px

Aplikacja będzie testowana w przeglądarce Google Chrome na trzech wiodących rozdzielczościach.

Dodatkowe wymagania

Użyj GitHub / Bitbucket do wersjonowania kodu. Proponuje użyć GitHub Pages do hostowania projektu. Mile widziane stosowanie metodologii BEM w CSS.

Dokumentacja

Dokumentacja projektu powinna zawierać:

  • Wstęp.
  • Opis struktury serwisu.
  • Opis technologii zastosowanych przy tworzeniu serwisu.
  • Testy.
  • Podsumowanie.

Podsumowanie

Zrealizowanie wszystkich założeń projektowych jest niezbędne do zaliczenia przedmiotu. Stosowanie dobrych praktyk projektowych (np. responsywność, dostępność, przejrzysty kod) przyniesie korzyści w postaci użytecznej i estetycznej aplikacji internetowej.