Szerző: Attila

  • Helyesírás és elütés

    Helyesírás és elütés

    Megkértem az AI-t, hogy nézze át a blogban szereplő bejegyzéseket, és keressen helyesírási hibákat, elütéseket. Elég sokat talált. Látszik, hogy sosem volt erősségem.

    Az a helyzet, hogy egyre több olyan feladatot találok neki, ami nekem igen sok időmet emésztené fel.

    A hqa.hu/blog felületén található bejegyzésekből és kivonatokból az alábbi helyesírási hibák, elütések, különírási/egybeírási tévesztések, valamint hiányzó ékezetek gyűjthetők össze:

    1. Különírási és egybeírási hibák

    • „Blog bejegyzések”Blogbejegyzések
      • Hiba: Összetett szóként egybeírandó.
    • „Energia ellátási probléma”Energiaellátási probléma
      • Hiba: Az energiaellátási összetett szó, egybeírandó (a szótagszáma és összetételi tagjai alapján is).
    • „energia felhasználásunkat”energiafelhasználásunkat
      • Hiba: Összetett szó, egybeírandó.
    • „másfelöl”másfelől(és külön/egybeírás/ékezet)
    • „végig néztem”végignéztem
      • Hiba: Az igekötő (végig) közvetlenül az ige előtt áll, így egybeírandó.
    • „realitás érzését”realitásérzését
      • Hiba: Jelöletlen birtokos összetétel, egybeírandó.
    • „mégis nincs kéznel egy darab példa kódom sem”példakódom
      • Hiba: Összetett szó, egybeírandó.
    • „válasz kód”válaszkód
      • Hiba: Egybeírandó összetett szó.
    • „működő képes”működőképes
      • Hiba: Egybeírandó melléknév.
    • „próbálta egy IDE-n belül kezelni a dolgokat (…) viszont egy idő után kezdet átláthatatlanná válni”(lásd lent a nyelvtani hibáknál is)

    2. Elütések és nyelvtani / alaktani hibák

    • „Azt hiszem, érdemes lesz ezt kipróbálom valamikor…”
      • Hiba: Helyesen: kipróbálnom (főnévi igeneves szerkezet/határozott ragozás hiánya: ezt kipróbálnom).
    • „…ámbár nem gyakran fordul elő, hogy a semmiből kell építkezi…”
      • Hiba: Elütés: építkezni (hiányzik az n betű).
    • „…amire én számítók…”
      • Hiba: Elütés: számítok (rövid o).
    • „…de ez az AI téma nagyon érdekel változásokat tartogat.”
      • Hiba: Értelmezési/fogalmazási elütés (valószínűleg: „nagyon sok változást tartogat” vagy „érdekes változásokat tartogat”).
    • „…kezdet átláthatatlanná válni…”
      • Hiba: Elütés: kezdett (múlt időben két t betű).
    • „mégis nincs kéznel…”
      • Hiba: Hiányzó ékezet / elütés: kéznél.
    • „…virtuális gépemről futottak a tesztek… irtam én is meg”
      • Hiba: Hiányzó ékezet: írtam.
    • „szerintem a videóban említett pontokat…” / „Majd kifejtem videóban említett…”
      • Hiba: Hiányzó névelő: „kifejtem a videóban említett…”.

    3. Hiányzó ékezetek és idegen szavak magyarítása

    • „definicióját”definícióját
      • Hiba: A definíció szóban a második i hosszú.
    • „vélemenyem”véleményem
      • Hiba: Hiányzó ékezet.
    • „sztenderdet” (vagy standardot)
      • Megjegyzés: Bár a sztenderd használható magyarított alak, a szakmai szövegekben gyakran keveredik a fonetikus és az angol helyesírással (standard).

    Összegzés

    A blogbejegyzésekben a leggyakrabban előforduló hibatípusok a különírt összetett szavak (pl. blog bejegyzés, válasz kód, példa kód, energia felhasználás), az igekötős igék különírása (végig néztem), valamint az apróbb gépelési elütések / ragozási tévesztések (kipróbálomkipróbálnom, építkeziépítkezni, kezdetkezdett).

  • Névnapok plugin Gemini-vel generálva

    Gondoltam egy merészet, és megkértem a Gemini-t, hogy készítsen nekem egy WordPress Plugint, ami random Mészáros Lőrinc idézeteket jelenít meg. Megcsinálta.

    “Abban, hogy eljutottam idáig, bizonyára szerepet játszik a Jóisten, a szerencse és Orbán Viktor személye, de én sohasem privatizáltam, mindent a saját munkámmal és eszemmel szereztem.”— Mészáros Lőrinc

    Nem álltam itt meg, megkértem, hogy csináljon egy névnap megjelenítőt, az aktuálisra, és a soron következőre.

    Ma: Tekla, Líviusz
    Holnap: Gellért, Mercédesz

    Íme:

    Itt egy komplett, egyfájlos WordPress bővítmény, amelyet közvetlenül beépíthetsz a weboldaladba. A bővítmény a látogató böngészőjének aktuális dátumát veszi alapul, kezeli a szökőéveket (a februári névnapeltolódást is), és shortcode segítségével bárhova könnyen elhelyezhető.

    Bővítmény kóda

    Hozz létre egy magyar-nevnapok.php fájlt a /wp-content/plugins/magyar-nevnapok/ mappában, és másold bele az alábbi kódot:

    PHP

    <?php
    /**
     * Plugin Name: Magyar Névnapok (Mai és Holnapi)
     * Description: Megjeleníti a mai és a holnapi névnapot shortcode segítségével.
     * Version: 1.0
     * Author: AI Assistant
     */
    
    if (!defined('ABSPATH')) {
        exit; // Közvetlen hozzáférés tiltása
    }
    
    class Magyar_Nevnapok_Plugin {
    
        // Névnap adatbázis (Hónap -> Nap -> Névnapok)
        private static $nevnapok = [
            1 => [
                1 => 'Fruzsina', 2 => 'Ábel', 3 => 'Genovéva, Benjámin', 4 => 'Titusz, Leona', 5 => 'Simon',
                6 => 'Boldizsár', 7 => 'Attila, Ramóna', 8 => 'Gyöngyvér', 9 => 'Marcell', 10 => 'Melánia',
                11 => 'Ágota', 12 => 'Ernő', 13 => 'Veronika', 14 => 'Bódog', 15 => 'Lóránt, Lóránd',
                16 => 'Gusztáv', 17 => 'Antal, Antónia', 18 => 'Piroska', 19 => 'Sára, Márió', 20 => 'Fábián, Sebestyén',
                21 => 'Ágnes', 22 => 'Vince, Artúr', 23 => 'Zelma, Rajmund', 24 => 'Timót', 25 => 'Pál',
                26 => 'Vanda, Paula', 27 => 'Angéla, Anzelm', 28 => 'Károly, Karola', 29 => 'Adél', 30 => 'Martina, Gerda',
                31 => 'Marcella'
            ],
            2 => [
                1 => 'Ignác', 2 => 'Karolina, Aida', 3 => 'Balázs', 4 => 'Ráhel, Csenge', 5 => 'Ágota, Ingrid',
                6 => 'Dorottya, Dóra', 7 => 'Tódor, Rómeó', 8 => 'Aranka', 9 => 'Abigél, Alex', 10 => 'Elvira',
                11 => 'Bertold, Marietta', 12 => 'Lívia, Lídia', 13 => 'Ella, Linda', 14 => 'Bálint, Valentin', 15 => 'Kolos, Georgina',
                16 => 'Julianna, Lilla', 17 => 'Donát', 18 => 'Bernadett', 19 => 'Zsuzsanna', 20 => 'Aladár, Álmos',
                21 => 'Eleonóra', 22 => 'Gerzson', 23 => 'Alfréd', 24 => 'Mátyás', 25 => 'Géza',
                26 => 'Edina', 27 => 'Ákos, Bátor', 28 => 'Elemér', 29 => 'Névnap szökőévben'
            ],
            3 => [
                1 => 'Albin', 2 => 'Lujza', 3 => 'Kornélia', 4 => 'Kázmér', 5 => 'Adorján, Adrián',
                6 => 'Leonóra, Inez', 7 => 'Tamás', 8 => 'Zoltán', 9 => 'Franciska, Fanni', 10 => 'Ildikó',
                11 => 'Szilárd', 12 => 'Gergely', 13 => 'Krisztián, Ajtony', 14 => 'Matild', 15 => 'Kristóf',
                16 => 'Henrietta', 17 => 'Patrick, Gertrúd', 18 => 'Ede, Sándor', 19 => 'József, Bánk', 20 => 'Klaudia',
                21 => 'Benedek', 22 => 'Beáta, Izolda', 23 => 'Emőke', 24 => 'Gábor, Karina', 25 => 'Irén, Írisz',
                26 => 'Emánuel', 27 => 'Hajnalka', 28 => 'Gedeon, Johanna', 29 => 'Auguszta', 30 => 'Zalán',
                31 => 'Árpád'
            ],
            4 => [
                1 => 'Hugó', 2 => 'Áron', 3 => 'Buda, Richárd', 4 => 'Izidor', 5 => 'Vince',
                6 => 'Vilmos, Bíbor', 7 => 'Herman', 8 => 'Dénes', 9 => 'Erhard', 10 => 'Zsolt',
                11 => 'Leó, Szaniszló', 12 => 'Gyula', 13 => 'Ida', 14 => 'Tibor', 15 => 'Anasztázia, Tas',
                16 => 'Csongor', 17 => 'Rudolf', 18 => 'Andrea, Ilma', 19 => 'Emma', 20 => 'Tivadar',
                21 => 'Konrád', 22 => 'Csilla, Noémi', 23 => 'Béla', 24 => 'György', 25 => 'Márk',
                26 => 'Ervin', 27 => 'Zita', 28 => 'Valéria', 29 => 'Péter', 30 => 'Katalin, Kitti'
            ],
            5 => [
                1 => 'Fülöp, Jakab', 2 => 'Zsigmond', 3 => 'Tímea, Irma', 4 => 'Mónika, Flórián', 5 => 'Györgyi',
                6 => 'Ivett, Frida', 7 => 'Gizella', 8 => 'Mihály', 9 => 'Gergely', 10 => 'Ármin, Pálmira',
                11 => 'Ferenc', 12 => 'Pongrác', 13 => 'Szervác, Imelda', 14 => 'Bonifác', 15 => 'Zsófia, Szonja',
                16 => 'Mózes, Botond', 17 => 'Paszkál', 18 => 'Erik, Alexandra', 19 => 'Ivó, Milán', 20 => 'Bernát, Felícia',
                21 => 'Konstantin', 22 => 'Júlia, Rita', 23 => 'Dezső', 24 => 'Eszter, Eliza', 25 => 'Orbán',
                26 => 'Fülöp, Evelin', 27 => 'Hella', 28 => 'Emil, Csanád', 29 => 'Magdolna', 30 => 'Janka, Zsanett',
                31 => 'Angéla, Petronella'
            ],
            6 => [
                1 => 'Tünde', 2 => 'Kármen, Anita', 3 => 'Klotild, Cecília', 4 => 'Bulcsú', 5 => 'Fatime, Fatima',
                6 => 'Norbert, Cintia', 7 => 'Róbert', 8 => 'Medárd', 9 => 'Félix', 10 => 'Margit, Gréta',
                11 => 'Barnabás', 12 => 'Villő', 13 => 'Antal, Anett', 14 => 'Vazul', 15 => 'Jolán, Vid',
                16 => 'Jusztin', 17 => 'Laura, Alida', 18 => 'Arnold, Levente', 19 => 'Gyárfás', 20 => 'Rafael',
                21 => 'Alajos, Leila', 22 => 'Paulina', 23 => 'Zoltán', 24 => 'Iván', 25 => 'Vilmos',
                26 => 'János, Pál', 27 => 'László', 28 => 'Levente, Irén', 29 => 'Péter, Pál', 30 => 'Pál'
            ],
            7 => [
                1 => 'Tihamér, Annamária', 2 => 'Ottó', 3 => 'Kornél, Soma', 4 => 'Ulrik', 5 => 'Emese, Sarolta',
                6 => 'Csaba', 7 => 'Apollónia', 8 => 'Ellák', 9 => 'Lukrécia', 10 => 'Amália',
                11 => 'Nóra, Lili', 12 => 'Izabella, Dalma', 13 => 'Jenő', 14 => 'Örs, Stella', 15 => 'Henrik, Roland',
                16 => 'Vali', 17 => 'Endre, Elek', 18 => 'Frigyes', 19 => 'Emília', 20 => 'Illés',
                21 => 'Dániel, Daniella', 22 => 'Magdolna', 23 => 'Lenke', 24 => 'Kinga, Kincső', 25 => 'Kristóf, Jakab',
                26 => 'Anna, Anikó', 27 => 'Olga, Liliána', 28 => 'Szabolcs', 29 => 'Márta, Flóra', 30 => 'Judit, Xénia',
                31 => 'Oszkár'
            ],
            8 => [
                1 => 'Boglárka', 2 => 'Lehel', 3 => 'Hermina', 4 => 'Domonkos, Dominika', 5 => 'Krisztina',
                6 => 'Berta, Bettina', 7 => 'Ibolya', 8 => 'László', 9 => 'Emőd', 10 => 'Lőrinc',
                11 => 'Zsuzsanna, Tiborc', 12 => 'Klára', 13 => 'Ipoly', 14 => 'Marcell', 15 => 'Mária',
                16 => 'Ábrahám', 17 => 'Jácint', 18 => 'Ilona', 19 => 'Huba', 20 => 'István',
                21 => 'Sámuel, Hajna', 22 => 'Menyhért', 23 => 'Bence', 24 => 'Bertalan', 25 => 'Lajos, Patrícia',
                26 => 'Izsó', 27 => 'Gáspár', 28 => 'Ágoston', 29 => 'Beatrix, Erna', 30 => 'Rózsa',
                31 => 'Erika, Bella'
            ],
            9 => [
                1 => 'Egyed, Egon', 2 => 'Rezső', 3 => 'Hilda', 4 => 'Rozália', 5 => 'Viktor, Lőrinc',
                6 => 'Zakariás', 7 => 'Regina', 8 => 'Mária, Adrienn', 9 => 'Ádám', 10 => 'Nikolett, Hunor',
                11 => 'Teodóra', 12 => 'Mária', 13 => 'Kornél', 14 => 'Szeréna, Roxána', 15 => 'Enikő, Melitta',
                16 => 'Edit', 17 => 'Zsófia', 18 => 'Diána', 19 => 'Vilhelmina', 20 => 'Friderika',
                21 => 'Máté, Mirella', 22 => 'Mór, Gellért', 23 => 'Tekla, Líviusz', 24 => 'Gellért, Mercédesz', 25 => 'Eufrozina, Kende',
                26 => 'Jusztina', 27 => 'Adalbert', 28 => 'Vencel', 29 => 'Mihály', 30 => 'Jeromos'
            ],
            10 => [
                1 => 'Malvin', 2 => 'Petra', 3 => 'Helga', 4 => 'Ferenc', 5 => 'Aurél',
                6 => 'Brúnó, Renáta', 7 => 'Amália', 8 => 'Koppány', 9 => 'Dénes', 10 => 'Gedeon',
                11 => 'Brigitta', 12 => 'Miksa', 13 => 'Kálmán, Ede', 14 => 'Helén', 15 => 'Teréz',
                16 => 'Gál', 17 => 'Hedvig', 18 => 'Lukács', 19 => 'Nándor', 20 => 'Vendel',
                21 => 'Orsolya', 22 => 'Előd', 23 => 'Gyöngyi', 24 => 'Salamon', 25 => 'Blanka, Bianca',
                26 => 'Dömötör', 27 => 'Szabina', 28 => 'Simon, Szimonetta', 29 => 'Nárcisz', 30 => 'Alfonz',
                31 => 'Farkas'
            ],
            11 => [
                1 => 'Marianna', 2 => 'Achilles', 3 => 'Győző', 4 => 'Károly', 5 => 'Imre',
                6 => 'Lénárd', 7 => 'Rezső', 8 => 'Zsombor', 9 => 'Tivadar', 10 => 'Réka',
                11 => 'Márton', 12 => 'Jónás, Renátó', 13 => 'Szilvia', 14 => 'Aliz', 15 => 'Albert, Lipót',
                16 => 'Ödön', 17 => 'Hortenzia, Gergő', 18 => 'Jenő', 19 => 'Erzsébet', 20 => 'Jolán',
                21 => 'Olivér', 22 => 'Cecília', 23 => 'Klementina', 24 => 'Emma', 25 => 'Katalin',
                26 => 'Virág', 27 => 'Virgil', 28 => 'Stefánia', 29 => 'Taksony', 30 => 'András, Andor'
            ],
            12 => [
                1 => 'Elza', 2 => 'Melinda, Vivien', 3 => 'Ferenc, Olívia', 4 => 'Borbála, Barbara', 5 => 'Vilma',
                6 => 'Miklós', 7 => 'Ambrus', 8 => 'Mária', 9 => 'Natália', 10 => 'Judit',
                11 => 'Árpád', 12 => 'Gabriella', 13 => 'Luca, Otília', 14 => 'Szilárda', 15 => 'Valér',
                16 => 'Etelka, Aletta', 17 => 'Lázár, Olimpia', 18 => 'Auguszta', 19 => 'Viola', 20 => 'Teofil',
                21 => 'Tamás', 22 => 'Zénó', 23 => 'Viktória', 24 => 'Ádám, Éva', 25 => 'Eugénia',
                26 => 'István', 27 => 'János', 28 => 'Kamilla', 29 => 'Tamás, Szeréna', 30 => 'Dávid',
                31 => 'Szilveszter'
            ]
        ];
    
        public function __construct() {
            add_shortcode('nevnapok', [$this, 'render_shortcode']);
        }
    
        /**
         * Névnap lekérése adott dátumra (kezeli a szökőéveket)
         */
        private function get_nevnap_by_timestamp($timestamp) {
            $month = (int)date('n', $timestamp);
            $day = (int)date('j', $timestamp);
            $is_leap_year = (date('L', $timestamp) == 1);
    
            // Szökőév esetén február 24. után a névnapok 1 nappal eltolódnak
            if ($is_leap_year && $month == 2) {
                if ($day == 24) {
                    return 'Szökőnap (Nincs külön névnap)';
                } elseif ($day > 24) {
                    $day--; // Február 25-29. a 24-28-ai névnapokat kapja
                }
            }
    
            return isset(self::$nevnapok[$month][$day]) ? self::$nevnapok[$month][$day] : 'Ismeretlen';
        }
    
        /**
         * Shortcode megjelenítése: [nevnapok]
         */
        public function render_shortcode($atts) {
            // Alapértelmezett beállítások felülírhatósága
            $atts = shortcode_atts([
                'mai_label'     => 'Mai névnap:',
                'holnapi_label' => 'Holnapi névnap:',
                'layout'        => 'block' // 'block' vagy 'inline'
            ], $atts, 'nevnapok');
    
            // WordPress időzóna beállítása alapján kérjük le az időt
            $now = current_time('timestamp');
            $tomorrow = strtotime('+1 day', $now);
    
            $mai_nevnap = $this->get_nevnap_by_timestamp($now);
            $holnapi_nevnap = $this->get_nevnap_by_timestamp($tomorrow);
    
            // HTML kimenet előállítása
            ob_start();
            ?>
            <div class="magyar-nevnapok-container layout-<?php echo esc_attr($atts['layout']); ?>">
                <div class="nevnap-item nevnap-mai">
                    <span class="nevnap-label"><?php echo esc_html($atts['mai_label']); ?></span>
                    <span class="nevnap-name"><?php echo esc_html($mai_nevnap); ?></span>
                </div>
                <div class="nevnap-item nevnap-holnapi">
                    <span class="nevnap-label"><?php echo esc_html($atts['holnapi_label']); ?></span>
                    <span class="nevnap-name"><?php echo esc_html($holnapi_nevnap); ?></span>
                </div>
            </div>
            <style>
                .magyar-nevnapok-container.layout-inline {
                    display: flex;
                    gap: 15px;
                    align-items: center;
                }
                .magyar-nevnapok-container .nevnap-label {
                    font-weight: bold;
                    margin-right: 4px;
                }
            </style>
            <?php
            return ob_get_clean();
        }
    }
    
    // Bővítmény inicializálása
    new Magyar_Nevnapok_Plugin();
    

    Használati útmutató

    1. Telepítés:
      • Hozz létre egy magyar-nevnapok nevű mappát a weboldalad wp-content/plugins/ könyvtárában.
      • Mentsd el a fenti kódot magyar-nevnapok.php néven ebbe a mappába.
      • Lépj be a WordPress admin felületére, és kapcsold be a Magyar Névnapok (Mai és Holnapi) bővítményt.
    2. Megjelenítés Shortcode-csal:Bármelyik oldalra, bejegyzésbe, widgetsávba vagy fejlécbe beillesztheted az alábbi shortcode-ok egyikét:
      • Alapértelmezett (blokk elrendezés):[ nevnapok ]
      • Egymás melletti (egysoros) elrendezés:[ nevnapok layout="inline" ]
      • Egyedi feliratok használata:[ nevnapok mai_label="Ma:" holnapi_label="Holnap:" layout="inline" ]

    1.Fájl létrehozása:

    Hozd létre a magyar-nevnapok.php fájlt a wp-content/plugins/magyar-nevnapok/ könyvtárban.

    2.Aktiválás:

    Lépj be a WordPress Adminba -> Bővítmények, majd aktiváld a „Magyar Névnapok” nevű bővítményt.

    3.Shortcode elhelyezése:

    Szúrd be a [ nevnapok ] shortcode-ot tetszőleges oldalba, blokkba vagy widgetbe.

  • JMeter, változó terhelésű tesztelés

    JMeter, változó terhelésű tesztelés

    Mint már korábban talán írtam, nem vagyok egy JMeter guru. Így aztán ha felmerül valami kérdés, az AI-hoz fordulok, mintsem órákat töltsek azzal, hogy a Google segítségével talált linkeket végigolvassam.  Így történt ez most is, amikor egy váltakozó terhelésű tesztet szerettem volna előállítani. Az elmélet megvolt, hiszen csináltam már ilyen HP LoadRunnerrel réges régen, viszont a JMeter beállításaival és technikai adottságaival nem vagyok komfortos, mivel ez egy elég jól konfigurálható „műszer”.

    Nézzük, mint mondott a Gemini:

    Egyszerű eset

    JMeterben a változó terhelésű (ramping, lépcsőzetes vagy hullámzó) tesztelés megvalósítására három fő módszer létezik, a legegyszerűbb beépített megoldástól a legrugalmasabb pluginokig.

    1. Beépített megoldás: Standard Thread Group

    Ha nincs lehetőséged pluginokat telepíteni, a sima Thread Group beállításaival is elérhetsz alapvető terhelésnövekedést (Ramp-up).

    • Ramp-up Period (seconds): Megadja, hogy a virtuális felhasználók mennyi idő alatt induljanak el fokozatosan.
    • Példa beállítás:
      • Number of Threads (users):100
      • Ramp-up Period (seconds):50
      • Loop Count:Infinite (vagy adj meg egy fix időtartamot a Specify Thread lifetime opcióval)
    • Működés: 50 másodperc alatt másodpercenként 2 új virtuális felhasználó lép be, amíg el nem éri a 100-at.

    2. A legrugalmasabb módszer: Ultimate Thread Group (Ajánlott)

    A változó terhelés (pl. hullámzás, lépcsőzetes emelés, hirtelen tüskék/spike tesztek) grafikusan és precízen a JMeter Plugins Manager segítségével telepíthető Custom Thread Groups csomaggal valósítható meg.

    A telepítés után válaszd a jp@gc - Ultimate Thread Group elemet. Ebben egy táblázatban (Threads Schedule) tetszőleges számú terhelési szakaszt kombinálhatsz:

    Start Thread CountInitial Delay (sec)Startup Time (sec)Hold Load For (sec)Shutdown Time (sec)
    1000306010
    200903012020
    • Működés:
      1. Az első sor lefut: 30 mp alatt felmegy 100 felhasználóra, tartja 60 mp-ig, majd leáll.
      2. A második sor 90 mp várakozás után belép, és további 200 felhasználóval megemeli a terhelést (lépcsőzetes teszt).

    3. Kérés/másodperc (RPS/TPS) alapú szabályozás

    Ha nem a virtuális felhasználók száma, hanem a másodpercenkénti kérésszám (Throughput) változtatása a célod:

    1. Throughput Shaping Timer (Plugin):
      • Helyezd a kérések alá (vagy a Thread Group szintjére).
      • Egy táblázatban megadhatod a kívánt RPS-t időtartam alapján:
        • Start RPS:10$\rightarrow$End RPS:50 (Duration:60s) — lineáris emelkedés
        • Start RPS:50$\rightarrow$End RPS:50 (Duration:180s) — állandó terhelés tartása
    2. Concurrency Thread Group + Throughput Shaping Timer:
      • A két plugin összekapcsolható (a Concurrency Thread Group automatikusan beállítja a szükséges virtuális felhasználók számát a Throughput Shaping Timer által kért RPS eléréséhez).

    Gyors összefoglaló a megközelítés kiválasztásához

    • Lépcsőzetes / Hullámzó terhelés userekkel: Use jp@gc - Ultimate Thread Group
    • Fix Target RPS / Áteresztőképesség tesztelése: Use Throughput Shaping Timer
    • Egyszerű lineáris felfutás: Standard Thread Group (Ramp-Up Period)

    Több Thread Group esetén

    Ha több Thread Group-ot használsz egyetlen Test Planen belül, akkor összetett, valósághű terhelési profilokat építhetsz fel. Például szimulálhatsz különböző felhasználói viselkedéseket (pl. 70% vásárló, 30% böngésző) vagy egymásra csúsztatott terhelési hullámokat.

    A több Thread Group összehangolására két alapvető megközelítés létezik: Párhuzamos (egyszerre futnak) és Egymás utáni (szekvenciális).

    1. Párhuzamos futtatás (Alapértelmezett beállítás)

    Alapértelmezetten a JMeter az összes Thread Group-ot egyszerre, párhuzamosan kezdi el futtatni. A változó terhelést az határozza meg, hogy a csoportok időben hogyan vannak beidőzítve egymáshoz képest.

    Példa scenárió: Vásárlási csúcsforgalom szimulációja

    • Thread Group A (Állandó háttérterhelés – Cikkolvasók): Folyamatosan jelen lévő felhasználók.
    • Thread Group B (Lépcsőzetes terhelés – Vásárlók): Hullámokban érkező vásárlók.

    Beállítás Ultimate Thread Group pluginnal:

    Test Plan

    • ⚙️ Test Plan(a „Run Thread Groups consecutively” opció kivétele)
      • 👥 jp@gc - Ultimate Thread Group(Háttérterhelés – Böngészők)
      • 👥 jp@gc - Ultimate Thread Group(Csúcsforgalom – Vásárlók)

    A) Háttérterhelés csoport (Böngészők):

    Start Thread CountInitial Delay (sec)Startup Time (sec)Hold Load For (sec)Shutdown Time (sec)
    5001030010

    (Gyorsan feláll 50 felhasználóra, és végig fut 5 percig.)

    B) Csúcsforgalom csoport (Vásárlók):

    Start Thread CountInitial Delay (sec)Startup Time (sec)Hold Load For (sec)Shutdown Time (sec)
    10060306010
    200180306010

    (A teszt 1. percében belép 100 vásárló, majd a 3. percben egy újabb 200 fős tüske érkezik.)

    2. Szekvenciális (Egymás utáni) futtatás

    Ha a terhelési fázisokat szigorúan egymás után akarod futtatni (pl. Felfűtés $\rightarrow$ Terhelési teszt $\rightarrow$ Kiürülés), be kell kapcsolnod a JMeterben az egymás utáni futtatást.

    Beállítás lépései:

    1. Kattints a Test Plan gyökérelemre.
    2. Pipáld be a Run Thread Groups consecutively (i.e. run one at a time) opciót.

    Példa felépítés:

    Test Plan(Egymás utáni futtatás bekapcsolva)

    • 1️⃣ Thread Group - 1. Fázis (Bemelegítés)
      • Threads: 20, Ramp-Up: 20s, Duration: 60s
    • 2️⃣ Thread Group - 2. Fázis (Fő terhelés)
      • Threads: 200, Ramp-Up: 30s, Duration: 300s
    • 3️⃣ Thread Group - 3. Fázis (Lecsengés)
      • Threads: 10, Ramp-Up: 1s, Duration: 30s
    • Működés: A JMeter megvárja, amíg az 1. csoport teljesen leáll, és csak utána indítja el a 2. csoportot, majd végül a 3.-at.

    💡 Fontos tipp adatok megosztásához a Thread Groupok között

    Ha több Thread Groupot használsz, a sima JMeter változók (${var}) nem terjednek át az egyik csoportból a másikba, mert a változók szál-specifikusak.

    Ha az egyik csoportban (pl. Bejelentkezés) generált adatot akarod használni egy másik csoportban:

    • Használj JMeter Property-ket a megosztáshoz (pl. Groovy scriptben: props.put("token", "${extracted_token}") és a másik csoportban: ${__P(token)}).
    • Használj jp@gc - Inter-Thread Communication plugint az adatok átadására a csoportok között.
  • Állásra jelentkezés

    Tegnap futottam rá erre a képére LinkedIn-en.

    Valahogy nagyon valósághűnek érzem. Aki mostanában pályázott állásra, ha nem is minden esetben, de nem kevésben viszont ezzel találkozhatott. Volt olyan pályázat, amit pont azért hagytam félbe, mert miután feltöltöttem az önéletrajzomat, átvitt egy másik oldalra, ahol az önéletrajz alapján próbálta kitölteni a lapot, természetesen brutális rosszul. Ekkor mérlegelve, hogy még ott kézzel minden egyes munkámról, tapasztalatomról írjak, úgy döntöttem, hogy nem. Persze, erre vannak, aki azt mondják, hogy nekem kell az állás. Igen, de nem minden áron, és nem úgy, hogy nem kevés energiát fektet az ember egy hirdetésbe, jelentkezésbe, interjúkba, majd pedig sok esetben még válaszra se méltatnak

    Nem is olyan rég volt olyan esetem, hogy szóban megállapodtunk, aztán utána csönd, meggondolták magukat, és elfelejtettek értesíteni.

    Barátom esete sem gyenge, mikor a 4. kör után megszűnt a visszajelzés.

    Szóval azt érzem, hogy nagyon el van szaladva az a ló a munkáltatói oldalon. Teljesen elvesztették a kapcsolatukat a valósággal, az emberségről nem beszélve. Döbbenetes, ami ma a munkaerőpiacon zajlik.

  • Ingyen kávé az irodában

    Ingyen kávé az irodában

    Minap volt ez a cikk a Telexen, ami nem kis indulatot váltott ki belőlem. Sose felejtem el az első munkahelyeimet, ahol semmi sem volt, még a bér is fekete vagy épp szürke zónás, de azon kívül semmi. Aztán szépen sikerült előre lépnem szakmailag és cég tekintetében, és bár életem igen nagy részében multinál dolgoztam, az ingyenes kávé alap volt ezeken a helyeken. Volt, hol jobb, máshol kevésbé jobb minőségben, de volt. Aztán volt olyan cég is, ahol a falból folyt a kóla. Ilyen is van. Ezzel szemben nagyon nehéz megérteni azon munkáltatókat, akik erre egyáltalán nem áldoznak.

    Ez szerintem egy olyan alap gesztus kéne, hogy legyen, ami arra hivatott, hogy jól érezd a bent töltött időt, attól nem beszélve, hogy az IT pont az a szakma, ahol igen magasan reprezentált a kávéfogyasztás, ami valószínűleg betudható annak a pörgésnek, és túlmunkának, ami ezzel jár.

    Szóval privát véleményem, hogy lehet erre, mint az otthoni munkavégzés megszüntetésére érveket keresni, csak épp nincs értelme, mert a valóság szembe megy ezekkel.

    Más részről pedig egy barátomtól hallott mondás jut eszembe, „ki banánnal fizet, az majmot kap”.

  • Apache JMeter és a Throughput Controller

    Mivel napo óta ezzel szórakoztatom magam, gondoltam íratok erről pár sort az AI-val, mint emlékeztető, ha újra elő kell vennem a témát. Röviden: vannak esetek, amikor százalékos arányban kell hívásokat eszközölni a performancia mérésben. Ebben tud segíteni a Throughput Controller.

    Nézzük, mint mond erről az AI:

    A Throughput Controller az Apache JMeter egyik legfontosabb eleme, amikor a valós felhasználói viselkedést szeretnénk szimulálni. Neve ellenére nem a másodpercenkénti kérések számát (RPS) korlátozza (arra a Constant Throughput Timer való), hanem azt határozza meg, hogy a teszt lépései milyen arányban vagy rögzített alkalommal fussanak le.

    Mire jó a Throughput Controller?

    Egy webáruháznál a látogatók nem egyforma arányban böngésznek és vásárolnak:

    • 80% csak böngészi a termékeket.
    • 15% kosárba tesz valamit.
    • 5% eljut a fizetésig.

    A Throughput Controller segítségével pontosan ezt a megoszlást képezhetjük le egyetlen Thread Group-on belül.

    A két fő működési mód (Based On)

    MódLeírásMikor használd?
    Percent ExecutionsA beállított százalékos arányban engedi lefutni a gyermek kéréseket a teszt során.Valós felhasználói eloszlás szimulálásához (pl. 80-15-5% szabály).
    Total ExecutionsLegfeljebb egy megadott fix alkalommal engedi lefutni a kérést, utána kihagyja.Egyszeri beállításokhoz vagy korlátozott műveletekhez (pl. adatbázis-feltöltés).

    Fontos beállítás (Per User): Ha be van pipálva, a számítás nem a teljes tesztre, hanem szálanként (felhasználónként) érvényesül.

    Gyakorlati példa: Webáruház forgalomszimuláció

    Tételezzük fel, hogy 100 szálat (felhasználót) indítunk egy hurokban (Loop Count: 100). A célunk a fent említett 80%-15%-5%-os megoszlás.

    Struktúra a JMeterben:

    Plaintext

    Test Plan
     └── Thread Group (100 Threads, Loop: 10)
          ├── Throughput Controller (Percent Executions: 80.0)
          │    └── HTTP Request: Termékoldal megtekintése
          ├── Throughput Controller (Percent Executions: 15.0)
          │    └── HTTP Request: Kosárba helyezés
          └── Throughput Controller (Percent Executions: 5.0)
               └── HTTP Request: Fizetés
    

    Működés:

    • A 1000 összes lefutásból nagyjából 800 alkalommal a termékoldal kérés fog lefutni.
    • 150 alkalommal a kosárba helyezés.
    • 50 alkalommal pedig a fizetés lép fel.

    Gyakori hibák és tippek

    1. Ne keverd a Constant Throughput Timer-rel: Ha az a célod, hogy a szervert pontosan 100 req/sec terhelés alatt tartsd, használj Timert. A Throughput Controller az arányokról szól, nem a sebességről.
    2. Keresztülfutás (Overhead): Ha a szabályok összege nem 100%, vagy egy szál egyik controllernek sem felel meg az adott iterációban, a szál kihagyja az adott részt és lép a következő hurokra.
    3. Egymásba ágyazás: Összetettebb scenárióknál Simple Controller-rel vagy Transaction Controller-rel kombinálva egész folyamatokat is elhelyezhetsz egy-egy Throughput Controller alá.
  • POM avagy Page Object Model

    Mire jó az AI? Hát például arra, hogy ha írni szeretnék egy témáról, de lusta vagyok, az egyébként is Google segítsével összeszedett információkat rendszerbe szedni, akkor relatív gyorsan kézhez kapok egy bejegyzést.

    A Page Object Model (POM) a szoftvertesztelés-automatizálás egyik legnépszerűbb és leghatékonyabb tervezési mintája (Design Pattern). A lényege, hogy az alkalmazás egyes weboldalait (vagy oldalrészeit) különálló objektumokként képezi le a kód szintjén.

    Miért érdemes használni?

    • Karbantarthatóság: Ha megváltozik egy gomb ID-ja vagy egy mező elhelyezkedése, elegendő azt egyetlen helyen (a Page Object osztályban) átírni, a teszteseteket nem kell bántani.
    • Kód újrafelhasználhatósága: A gyakori műveletek (pl. bejelentkezés, keresés) egyszer vannak megírva, és bármelyik tesztből meghívhatók.
    • Olvashatóság: A tesztkód tiszta, átlátható és üzleti logikát követő lesz, rejtve a techniai megvalósítást (pl. DOM-lekérdezéseket).

    Minta megvalósítás (Python + Selenium)

    Az alábbiakban egy klasszikus bejelentkezési folyamat példáján keresztül látható a POM működése.

    A Page Object osztály (login_page.py)

    Ez az osztály tartalmazza az oldal elemeinek azonosítóit (lokátorait) és a végezhető műveleteket.

    Python

    from selenium.webdriver.common.by import By
    
    class LoginPage:
        def __init__(self, driver):
            self.driver = driver
            
            # Lokátorok (különválasztva a logikától)
            self._username_input = (By.ID, "username")
            self._password_input = (By.ID, "password")
            self._login_button = (By.CSS_SELECTOR, "button[type='submit']")
            self._error_message = (By.CLASS_NAME, "flash-error")
    
        # Akciók / Műveletek
        def enter_username(self, username: str):
            self.driver.find_element(*self._username_input).send_keys(username)
    
        def enter_password(self, password: str):
            self.driver.find_element(*self._password_input).send_keys(password)
    
        def click_login(self):
            self.driver.find_element(*self._login_button).click()
    
        # Összetett folyamat (Láncolt / Magasabb szintű akció)
        def login(self, username: str, password: str):
            self.enter_username(username)
            self.enter_password(password)
            self.click_login()
    
        def get_error_message(self) -> str:
            return self.driver.find_element(*self._error_message).text
    

    A Teszteset (test_login.py)

    A tesztkód csak a Page Object által nyújtott metódusokat használja, így végtelenül egyszerű és olvasható.

    Python

    import pytest
    from selenium import webdriver
    from login_page import LoginPage
    
    @pytest.fixture
    def driver():
        driver = webdriver.Chrome()
        driver.get("https://example.com/login")
        yield driver
        driver.quit()
    
    def test_successful_login(driver):
        login_page = LoginPage(driver)
        
        # Bejelentkezés végrehajtása
        login_page.login("valid_user", "correct_password")
        
        # Ellenőrzés (Assertion)
        assert driver.current_url == "https://example.com/dashboard"
    
    def test_failed_login(driver):
        login_page = LoginPage(driver)
        
        login_page.login("invalid_user", "wrong_password")
        
        # Hibaüzenet ellenőrzése
        assert "Érvénytelen adatok" in login_page.get_error_message()
    

    Jó tanácsok a gyakorlati alkalmazáshoz

    • Ne tegyél assertion-öket a Page Object-be: A assert kifejezések a tesztfájlban maradjanak, a Page Object csak adatot adjon vissza vagy állapotot módosítson.
    • Page Factory használata: Bizonyos keretrendszerekben (pl. Java + Selenium) a @FindBy annotációkkal még tisztább szerkezet érhető el.
    • Lazy loading: Az elemeket csak akkor kérd le a DOM-ból, amikor ténylegesen szükség van rájuk (például dinamikus felületek esetén).

    A Page Object Model (POM) megvalósítása a modernebb eszközökkel (mint a Playwright vagy a Selenium Java-alapú változata) még letisztultabbá válik, mivel ezek a keretrendszerek beépített architektúrával támogatják a megbízhatóbb elemkezelést.

    Az alábbiakban mindkét megközelítésre találsz egy-egy komplett kódmintát.

    Playwright + TypeScript (Ajánlott / Modern megközelítés)

    A Playwright eleve magában foglalja az automatikus várakozást (Auto-waiting), így nincs szükség explicit wait-ek kézi kezelésére.

    A Page Object osztály (pages/LoginPage.ts)

    TypeScript

    import { Page, Locator } from '@playwright/test';
    
    export class LoginPage {
      readonly page: Page;
      readonly usernameInput: Locator;
      readonly passwordInput: Locator;
      readonly loginButton: Locator;
      readonly errorMessage: Locator;
    
      constructor(page: Page) {
        self.page = page;
        // A Playwright-ban a lokátorok deklaratívak, nem kérdezik le azonnal a DOM-ot
        this.usernameInput = page.locator('#username');
        this.passwordInput = page.locator('#password');
        this.loginButton = page.locator('button[type="submit"]');
        this.errorMessage = page.locator('.flash-error');
      }
    
      async goto() {
        await this.page.goto('https://example.com/login');
      }
    
      async login(username: string, password: string) {
        await this.usernameInput.fill(username);
        await this.passwordInput.fill(password);
        await this.loginButton.click();
      }
    
      async getErrorMessage(): Promise<string> {
        return await this.errorMessage.textContent() || '';
      }
    }
    

    A Tesztfájl (tests/login.spec.ts)

    TypeScript

    import { test, expect } from '@playwright/test';
    import { LoginPage } from '../pages/LoginPage';
    
    test.describe('Bejelentkezés tesztek', () => {
      let loginPage: LoginPage;
    
      test.beforeEach(async ({ page }) => {
        loginPage = new LoginPage(page);
        await loginPage.goto();
      });
    
      test('Sikeres bejelentkezés', async ({ page }) => {
        await loginPage.login('valid_user', 'correct_password');
        
        // Ellenőrzés Playwright assert-tel
        await expect(page).toHaveURL('https://example.com/dashboard');
      });
    
      test('Hibás bejelentkezés', async () => {
        await loginPage.login('invalid_user', 'wrong_password');
        
        await expect(loginPage.errorMessage).toBeVisible();
        await expect(loginPage.errorMessage).toContainText('Érvénytelen adatok');
      });
    });
    

    Java + Selenium (Klasszikus keretrendszer)

    Java környezetben a PageFactory és a @FindBy annotációk használata a legelterjedtebb POM minta.

    A Page Object osztály (LoginPage.java)

    Java

    package pages;
    
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.WebElement;
    import org.openqa.selenium.support.FindBy;
    import org.openqa.selenium.support.PageFactory;
    
    public class LoginPage {
        private WebDriver driver;
    
        // Lokátorok deklarálása annotációkkal
        @FindBy(id = "username")
        private WebElement usernameInput;
    
        @FindBy(id = "password")
        private WebElement passwordInput;
    
        @FindBy(css = "button[type='submit']")
        private WebElement loginButton;
    
        @FindBy(className = "flash-error")
        private WebElement errorMessage;
    
        // Konstruktor: inicializálja a PageFactory elemeit
        public LoginPage(WebDriver driver) {
            this.driver = driver;
            PageFactory.initElements(driver, this);
        }
    
        public void enterUsername(String username) {
            usernameInput.clear();
            usernameInput.sendKeys(username);
        }
    
        public void enterPassword(String password) {
            passwordInput.clear();
            passwordInput.sendKeys(password);
        }
    
        public void clickLogin() {
            loginButton.click();
        }
    
        public void login(String username, String password) {
            enterUsername(username);
            enterPassword(password);
            clickLogin();
        }
    
        public String getErrorMessageText() {
            return errorMessage.getText();
        }
    }
    

    A Tesztosztály (JUnit 5 használatával) (LoginTest.java)

    Java

    package tests;
    
    import org.junit.jupiter.api.AfterEach;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import org.openqa.selenium.WebDriver;
    import org.openqa.selenium.chrome.ChromeDriver;
    import pages.LoginPage;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    import static org.junit.jupiter.api.Assertions.assertTrue;
    
    public class LoginTest {
        private WebDriver driver;
        private LoginPage loginPage;
    
        @BeforeEach
        public void setUp() {
            driver = new ChromeDriver();
            driver.manage().window().maximize();
            driver.get("https://example.com/login");
            loginPage = new LoginPage(driver);
        }
    
        @Test
        public void testSuccessfulLogin() {
            loginPage.login("valid_user", "correct_password");
            assertEquals("https://example.com/dashboard", driver.getCurrentUrl());
        }
    
        @Test
        public void testFailedLogin() {
            loginPage.login("invalid_user", "wrong_password");
            assertTrue(loginPage.getErrorMessageText().contains("Érvénytelen adatok"));
        }
    
        @AfterEach
        public void tearDown() {
            if (driver != null) {
                driver.quit();
            }
        }
    }
    

    Főbb különbségek a két megközelítés között

    SzempontPlaywright (TypeScript)Selenium (Java)
    LokátorokA Locator objektumok deklaratívak (auto-wait)A @FindBy elemek lekezeléséhez várakozás (WebDriverWait) kellhet
    PárhuzamosításAlapból támogatott a tesztfutztatóbanTestNG vagy JUnit szálkezelést igényel
    InicializálásEgyszerű objektumkonstruktorPageFactory.initElements() hívás szükséges

    A Playwright Custom Fixture funkciója segítségével a Page Object osztályok példányosítását teljesen kiszervezheted a tesztekből. Ezzel elkerülhető, hogy minden egyes tesztfájlban manuálisan kelljen megadni a const loginPage = new LoginPage(page) sorokat.

    A tesztek így közvetlenül paraméterként kérhetik el a szükséges oldalobjektumokat, az infrastruktúra pedig automatikusan példányosítja és előkészíti azokat.

    A Page Object osztályok (pages/)

    A megszokott módon hozzuk létre az oldalklasszokat.

    TypeScript

    // pages/LoginPage.ts
    import { Page, Locator } from '@playwright/test';
    
    export class LoginPage {
      readonly page: Page;
      readonly usernameInput: Locator;
    
      constructor(page: Page) {
        this.page = page;
        this.usernameInput = page.locator('#username');
      }
    
      async goto() {
        await this.page.goto('/login');
      }
    }
    
    // pages/DashboardPage.ts
    import { Page, Locator } from '@playwright/test';
    
    export class DashboardPage {
      readonly page: Page;
      readonly userMenu: Locator;
    
      constructor(page: Page) {
        this.page = page;
        this.userMenu = page.locator('#user-menu');
      }
    }
    

    A Custom Fixture létrehozása (fixtures/baseTest.ts)

    Itt terjesztjük ki a Playwright alapértelmezett test objektumát, megadva a saját Page Object fixture-jeinket.

    TypeScript

    import { test as base } from '@playwright/test';
    import { LoginPage } from '../pages/LoginPage';
    import { DashboardPage } from '../pages/DashboardPage';
    
    // 1. Típusdefiníció a fixture-ökhöz
    type MyFixtures = {
      loginPage: LoginPage;
      dashboardPage: DashboardPage;
    };
    
    // 2. A 'base.extend' használatával regisztráljuk a saját fixture-jeinket
    export const test = base.extend<MyFixtures>({
      // Automatikusan példányosítja a LoginPage-t és igény esetén megnyitja az oldalt
      loginPage: async ({ page }, use) => {
        const loginPage = new LoginPage(page);
        await loginPage.goto(); // Akár előkészítő lépéseket is tehetünk ide
        await use(loginPage);   // Átadja az objektumot a tesztnek
      },
    
      // Példányosítja a DashboardPage-t
      dashboardPage: async ({ page }, use) => {
        const dashboardPage = new DashboardPage(page);
        await use(dashboardPage);
      },
    });
    
    // Az 'expect'-et is exportáljuk a kényelmes importálásért
    export { expect } from '@playwright/test';
    

    A Fixture-ök használata a tesztekben (tests/login.spec.ts)

    A @playwright/test helyett a saját fixtures/baseTest fájlunkból importáljuk a test objektumot. A tesztfüggvény paramétereként megadott nevek alapján a Playwright automatikusan beadagolja a megfelelő példányokat.

    TypeScript

    // Figyelem: A saját kiterjesztett test objektumunkat importáljuk!
    import { test, expect } from '../fixtures/baseTest';
    
    test('Sikeres bejelentkezés custom fixture-rel', async ({ loginPage, dashboardPage }) => {
      // A loginPage.goto() már lefutott a fixture-ben!
      await loginPage.usernameInput.fill('standard_user');
      
      // A dashboardPage is azonnal használható, nem kellett 'new'-val példányosítani
      await expect(dashboardPage.userMenu).toBeVisible();
    });
    

    Miért ez a legnépszerűbb Playwright architektúra?

    • Nulla boilerplate kód: Nem kell beforeEach blokkokban példányosítani az osztályokat.
    • Lazy loading (Lusta betöltés): Csak azok a Page Object-ek példányosulnak, amiket a teszt fejlécében ({ loginPage, dashboardPage }) kifejezetten elkérsz.
    • Beépített tear-down: A fixture-ben a use() hívás utáni kódrészlet automatikusan lefut a teszt végén (takarításra, kijelentkezésre ideális).
  • API G – Mi volt az igény?

    „busy, aki a héten nem szállít…”

    Mit mást is mondhatnék? Aki a szakmában dolgozni, szerintem sír a röhögéstől, miközben magára ismer 🙂

  • Legáltalánosabb GIT parancsok

    Legáltalánosabb GIT parancsok

    Sosem voltam egy nagy karakter húszár, így előnybe részesítettem a grafikus ezközöket. Mostanában viszont egyre gyakrabban kényszerűlők rá, hogy parancssorosan oldjak meg dolgok, mint pl a GIT-elést. Gondoltam AI-val összegyűjtetem a legáltalánosabb parancsokat.

    Infografika a Git alapvető parancsairól: inicializálás, módosítások követése, commit, ágkezelés és távoli tároló

    A leggyakrabban használt Git parancsok kategóriák szerint csoportosítva:

    Alapvető beállítások & Inicializálás

    • git config --global user.name "Neved" – Beállítja a felhasználóneved a commitokhoz.
    • git config --global user.email "email@cimed.hu" – Beállítja az e-mail-címedet.
    • git init – Új, üres Git repót hoz létre az aktuális mappában.
    • git clone <URL> – Letölt egy meglévő távoli tárolót (repository-t) a gépedre.

    Változások nyomon követése & Commit

    • git status – Megmutatja a munkamenet állapotát (módosított, követetlen fájlok).
    • git add <fájlnév> – Hozzáadja a megadott fájlt a Staging Area-hoz.
    • git add . – Az összes módosított és új fájlt hozzáadja a Staging Area-hoz.
    • git commit -m "Üzenet" – Elmenti a Staging Area-ban lévő változtatásokat a megadott üzenettel.
    • git diff – Megmutatja a még el nem mentett (unstaged) módosításokat.

    Nézet & Történet

    • git log – Megjeleníti a korábbi commitok történetét.
    • git log --oneline – Tömör, egysoros formátumban listázza a commitokat.

    Ágak kezelése (Branching)

    • git branch – Listázza a helyi ágakat.
    • git branch <ág-név> – Létrehoz egy új ágat.
    • git checkout <ág-név> – Átvált a megadott ágra.
    • git checkout -b <ág-név> – Létrehoz egy új ágat és egyből át is vált rá.
    • git merge <ág-név> – A megadott ág tartalmát összefésüli az aktuális ággal.

    Távoli tároló (Remote)

    • git fetch – Letölti az új információkat a távoli tárolóból, de nem egyesíti őket.
    • git pull – Letölti és azonnal összefésüli a távoli ág változásait.
    • git push origin <ág-név> – Feltölti a helyi commitokat a távoli tárolóba.

    Módosítások visszavonása

    • git restore <fájlnév> – Visszaállítja a fájlt a legutóbbi commit állapotára (eldobja a nem elmentett módosításokat).
    • git reset HEAD~1 – Visszavonja a legutóbbi commitot, de a fájlokban lévő módosításokat megőrzi.

    Git Parancsok Gyorsútmutató

    KategóriaParancsLeírás
    Beállítás & Kezdésgit config --global user.name "Neved"Felhasználónév beállítása
    git config --global user.email "email@cimed.hu"E-mail-cím beállítása
    git initÚj helyi repó inicializálása
    git clone <URL>Távoli tároló letöltése
    Változások Kezelésegit statusMunkamenet állapotának ellenőrzése
    git add <fájl> vagy git add .Fájl(ok) hozzáadása a Staging Area-hoz
    git commit -m "Üzenet"Változtatások véglegesítése üzenettel
    git diffNem elmentett módosítások megtekintése
    Történet & Ágakgit log --onelineCommit előzmények tömör listázása
    git branchHelyi ágak listázása
    git checkout -b <ág-név>Új ág létrehozása és átváltás
    git merge <ág-név>Ág összefésülése az aktuálissal
    Távoli Tároló (Remote)git pullFrissítések letöltése és összefésülése
    git push origin <ág-név>Helyi commitok feltöltése
    Módosítások Visszavonásagit restore <fájl>Nem elmentett módosítások eldobása
    git reset HEAD~1Legutóbbi commit visszavonása (fájlok megmaradnak)
  • Duplikációk keresése, avagy power shell script íratása AI-val

    Duplikációk keresése, avagy power shell script íratása AI-val

    Ma ilyen AI-s napom van. Egyre jobban tör be a mindennapi munkámba, és úgy tűnik, hogy a hétvégeimet is ez teszi ki. Miért? Kérdezheted joggal. Megmondom. Az IT-ban, de gyanítom a többi szakmában is jobb, ha értünk hozzá, és megtanuljuk rutinosan használni, mintsem lemaradjunk róla, és nézzük bambán, ahogy az élet felsuhan előttünk.

    Nézzük, mire is mentem elsőre.

    Az alábbi PowerShell-script végigpásztázza a megadott mappát (és annak almappáit), a fájlok SHA256 hash értéke alapján azonosítja a duplikációkat, majd az eredményt kiírja a képernyőre és elmenti egy CSV-fájlba.

    PowerShell duplikáció-kereső script

    Hozz létre egy find-duplicates.ps1 fájlt, és másold bele az alábbi kódot:

    PowerShell

    # --- BEÁLLÍTÁSOK ---
    $TargetFolder = "C:\Elérési\Út\A\Mappához"   # Cseréld ki a vizsgálandó mappa útvonalára
    $OutputFile   = "C:\Elérési\Út\duplikatumok.csv" # Ide menti az eredményt
    
    Write-Host "Fájlok indexelése és hash értékek számítása..." -ForegroundColor Cyan
    
    # 1. Összes fájl lekérése és méret szerinti csoportosítása (gyorsítási lépés)
    $fileGroups = Get-ChildItem -Path $TargetFolder -Recurse -File -ErrorAction SilentlyContinue |
        Group-Group-Object -Property Length |
        Where-Object { $_.Count -gt 1 }
    
    $duplicates = @()
    $totalGroups = $fileGroups.Count
    $counter = 0
    
    # 2. Csak az azonos méretű fájlok SHA256 hash-ének ellenőrzése
    foreach ($group in $fileGroups) {
        $counter++
        Write-Progress -Activity "Duplikátumok keresése" -Status "Fájlcsoportok feldolgozása: $counter / $totalGroups" -PercentComplete (($counter / $totalGroups) * 100)
    
        $hashTable = $group.Group | Get-FileHash -Algorithm SHA256 | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 }
    
        foreach ($hashGroup in $hashTable) {
            foreach ($file in $hashGroup.Group) {
                $duplicates += [PSCustomObject]@{
                    Hash     = $hashGroup.Name
                    Path     = $file.Path
                    SizeMB   = [math]::Round((Get-Item $file.Path).Length / 1MB, 2)
                }
            }
        }
    }
    
    # 3. Eredmények megjelenítése és mentése
    if ($duplicates.Count -gt 0) {
        Write-Host "`nTalált duplikátumok:" -ForegroundColor Green
        $duplicates | Format-Table -AutoSize -Property Hash, SizeMB, Path
    
        $duplicates | Export-Csv -Path $OutputFile -NoTypeInformation -Encoding UTF8
        Write-Host "Az eredmények elmentve ide: $OutputFile" -ForegroundColor Yellow
    } else {
        Write-Host "`nNem találhatók duplikált fájlok." -ForegroundColor Green
    }
    

    Így használd:

    1. Nyisd meg a PowerShell-t (akár Rendszergazdaként, ha védett mappákat is vizsgálsz).
    2. Írd át a $TargetFolder változót a keresni kívánt mappára.
    3. Futtasd a scriptet:PowerShell.\find-duplicates.ps1

    Megjegyzés: Ha a PowerShell letiltja a scriptek futtatását, futtasd ezt a parancsot a munkamenetben:

    Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process

    Majd második próbálkozásra

    Módosítottam a scriptet, hogy a célmappát (és opcióként a kimeneti CSV-fájl helyét is) paraméterként fogadja el.

    A módosított script kódja:

    PowerShell

    <#
    .SYNOPSIS
        Fájl duplikációkat kereső és gyűjtő PowerShell script.
    
    .DESCRIPTION
        A script végigpásztázza a paraméterként megadott mappát (és annak almappáit),
        és az SHA256 hash értékek alapján azonosítja a duplikátumokat.
        Az eredményt megjeleníti a konzolon és CSV-fájlba menti.
    
    .PARAMETER TargetFolder
        A vizsgálandó mappa útvonala (kötelező paraméter).
    
    .PARAMETER OutputFile
        A kimeneti CSV fájl útvonala (opcionális, alapértelmezett: .\duplikatumok.csv).
    #>
    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, Position = 0, HelpMessage = "Kérjük, adja meg a vizsgálandó mappa útvonalát!")]
        [ValidateScript({ Test-Path $_ -PathType Container })]
        [string]$TargetFolder,
    
        [Parameter(Mandatory = $false, Position = 1)]
        [string]$OutputFile = ".\duplikatumok.csv"
    )
    
    # Abszolút útvonalak feloldása
    $TargetFolder = (Resolve-Path $TargetFolder).Path
    $OutputFile   = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($OutputFile)
    
    Write-Host "Mappa elemzése: $TargetFolder" -ForegroundColor Cyan
    Write-Host "Fájlok indexelése és méret szerinti csoportosítása..." -ForegroundColor Cyan
    
    # 1. Összes fájl lekérése és méret szerinti csoportosítása (gyorsítási lépés)
    $fileGroups = Get-ChildItem -Path $TargetFolder -Recurse -File -ErrorAction SilentlyContinue |
        Group-Object -Property Length |
        Where-Object { $_.Count -gt 1 }
    
    $duplicates = @()
    $totalGroups = $fileGroups.Count
    $counter = 0
    
    if ($totalGroups -eq 0) {
        Write-Host "`nNem találhatók azonos méretű fájlok, nincsenek duplikátumok." -ForegroundColor Green
        exit
    }
    
    # 2. Csak az azonos méretű fájlok SHA256 hash-ének ellenőrzése
    foreach ($group in $fileGroups) {
        $counter++
        Write-Progress -Activity "Duplikátumok keresése" -Status "Fájlcsoportok feldolgozása: $counter / $totalGroups" -PercentComplete (($counter / $totalGroups) * 100)
    
        $hashTable = $group.Group | Get-FileHash -Algorithm SHA256 | Group-Object -Property Hash | Where-Object { $_.Count -gt 1 }
    
        foreach ($hashGroup in $hashTable) {
            foreach ($file in $hashGroup.Group) {
                $duplicates += [PSCustomObject]@{
                    Hash     = $hashGroup.Name
                    Path     = $file.Path
                    SizeMB   = [math]::Round((Get-Item $file.Path).Length / 1MB, 2)
                }
            }
        }
    }
    
    # 3. Eredmények megjelenítése és mentése
    if ($duplicates.Count -gt 0) {
        Write-Host "`nTalált duplikátumok:" -ForegroundColor Green
        $duplicates | Format-Table -AutoSize -Property Hash, SizeMB, Path
    
        $duplicates | Export-Csv -Path $OutputFile -NoTypeInformation -Encoding UTF8
        Write-Host "Az eredmények elmentve ide: $OutputFile" -ForegroundColor Yellow
    } else {
        Write-Host "`nNem találhatók duplikált fájlok." -ForegroundColor Green
    }
    

    Használati példák:

    1. Alapértelmezett használat (a mappa elérést megadva, az eredmény a beállítások szerint a duplikatumok.csv-be kerül):PowerShell.\find-duplicates.ps1 -TargetFolder "C:\Users\Public\Documents"
    2. Pozicionális paraméterként (nem kell kiírni a névadó kapcsolót):PowerShell.\find-duplicates.ps1 "D:\Képek"
    3. Egyedi CSV kimeneti fájlnév megadásával:PowerShell.\find-duplicates.ps1 -TargetFolder "D:\Dokumentumok" -OutputFile "C:\Riportok\doksi_duplikatumok.csv"

    Újdonságok a scriptben:

    • Automatikus mappa-ellenőrzés (ValidateScript): Ha nem létező vagy hibás mappa-útvonalat adsz meg, a script még a futás előtt jelez és leáll.
    • Mappa-kötelezőség (Mandatory = $true): Ha paraméter nélkül indítod el a scriptet, a PowerShell automatikusan megkérdezi tőled a célmappa útvonalát.

    Nem vagyok teljes mértékben elragadtatva az eredménytől, de mára ez bőven elég volt, majd folytatjuk…