Məqalələr

PHPUnit və PEST-dən istifadə edərək sadə nümunələrlə Laravel-də testlərin necə aparılacağını öyrənin

Avtomatlaşdırılmış testlərə və ya vahid testlərinə gəldikdə, hər hansı bir proqramlaşdırma dilində iki əks fikir var:

  • Vaxt itkisi
  • Onsuz edə bilməzsiniz

Beləliklə, bu məqalə ilə biz birincini inandırmağa çalışacağıq, xüsusən də Laravel-də avtomatlaşdırılmış testlərə başlamağın nə qədər asan olduğunu nümayiş etdirəcəyik.

Əvvəlcə "niyə" haqqında danışaq, sonra necə olduğuna dair bəzi nümunələrə baxaq.

Nə üçün bizə avtomatlaşdırılmış test lazımdır

Avtomatlaşdırılmış testlər kodun hissələrini işlədir və hər hansı səhvləri bildirir. Bu, onları təsvir etməyin ən sadə yoludur. Təsəvvür edin ki, bir tətbiqdə yeni bir funksiya təqdim olunur və sonra şəxsi robot köməkçisi gedib yeni funksiyanı əl ilə sınaqdan keçirəcək, eyni zamanda yeni kodun köhnə funksiyalardan heç birini pozmadığını yoxlayacaq.

Bu, əsas üstünlükdür: bütün funksiyaları avtomatik olaraq yenidən sınaqdan keçirmək. Bu, əlavə iş kimi görünə bilər, lakin siz “robota” bunu deməsəniz, alternativ olaraq bunu əl ilə etməliyik, elə deyilmi? 

Və ya istifadəçilərin səhvlər barədə məlumat verəcəyi ümidi ilə yeni funksiyalar işlək olub-olmadığını yoxlamadan buraxıla bilər.

Avtomatlaşdırılmış testlər bizə bir sıra üstünlüklər verə bilər:

  • Əl testi vaxtına qənaət edin;
  • Onlar reqressiyadan qaçaraq həm həyata keçirilən yeni funksiyaya, həm də birləşdirilmiş funksiyalara vaxta qənaət etməyə imkan verir;
  • Bu faydanı bütün yeni funksiyalar və artıq tətbiq edilmiş bütün xüsusiyyətlərlə çoxaltın;
  • Əvvəlki üç bənd hər yeni versiyaya aiddir;
  • ...

Tətbiqinizi bir və ya iki ildən sonra, komandada əvvəlki illərdə yazılmış kodu bilməyən, hətta onu necə sınaqdan keçirəcəyini bilməyən yeni tərtibatçılarla təsəvvür etməyə çalışın. 

İlk avtomatlaşdırılmış testlərimiz

Birinci yerinə yetirmək üçün Laravel-də avtomatlaşdırılmış sınaq, heç bir kod yazmağa ehtiyac yoxdur. Bəli, düz oxudunuz. Əvvəlcədən quraşdırmada hər şey artıq konfiqurasiya edilmiş və hazırlanmışdırdefiLaravel nite, o cümlədən ilk əsas nümunə.

Siz Laravel layihəsini quraşdırmağa cəhd edə və dərhal ilk testləri keçirə bilərsiniz:

laravel new project
cd project
php artisan test

Bu konsolunuzdakı nəticə olmalıdır:

Öncəsinə nəzər salsaqdefiLaravel gecəsi /tests, iki faylımız var:

testlər/Feature/ExampleTest.php :

class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/');
 
        $response->assertStatus(200);
    }
}

Burada nə baş verdiyini anlamaq üçün hər hansı sintaksisi bilməyə ehtiyac yoxdur: ana səhifəni yükləyin və status kodunun olub olmadığını yoxlayın. HTTP è "200 OK".

Metod adı kimi də tanınır test_the_application_returns_a_successful_response() test nəticələrinə baxdığınız zaman, sadəcə olaraq alt xətt simvolunu boşluqla əvəz etməklə oxuna bilən mətnə ​​çevrilir.

testlər/Unit/ExampleTest.php :

class ExampleTest extends TestCase
{
    public function test_that_true_is_true()
    {
        $this->assertTrue(true);
    }
}

Bir az mənasız görünür, bunun doğru olub olmadığını yoxlamaq lazımdır? 

Bir az sonra xüsusi olaraq vahid testləri haqqında danışacağıq. Hələlik, hər bir testdə ümumiyyətlə nə baş verdiyini başa düşməlisiniz.

  • Qovluqdakı hər bir test faylı /tests TestCase-i genişləndirən PHP sinfidir PHPUnit
  • Hər bir sinif daxilində birdən çox metod yarada bilərsiniz, adətən vəziyyətin sınaqdan keçirilməsi üçün bir üsul
  • Hər bir metod daxilində üç hərəkət var: vəziyyəti hazırlamaq, sonra hərəkətə keçmək və nəticənin gözlənildiyi kimi olub olmadığını yoxlamaq (təsdiq etmək).

Struktur olaraq, bilmək lazım olan hər şey budur, qalan hər şey sınamaq istədiyiniz dəqiq şeylərdən asılıdır.

Boş bir test sinfi yaratmaq üçün bu əmri yerinə yetirmək kifayətdir:

php artisan make:test HomepageTest

Fayl yaradılır tests/Feature/HomepageTest.php:

class HomepageTest extends TestCase
{
    // Replace this method with your own ones
    public function test_example()
    {
        $response = $this->get('/');
 
        $response->assertStatus(200);
    }
}

İndi görək Laravel-də test kodu uğursuz olarsa nə baş verir

İndi görək test təsdiqləmələri gözlənilən nəticəni qaytarmasa nə olacaq.

Nümunə testləri buna dəyişdirək:

class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/non-existing-url');
 
        $response->assertStatus(200);
    }
}
 
 
class ExampleTest extends TestCase
{
    public function test_that_true_is_false()
    {
        $this->assertTrue(false);
    }
}

İndi, əgər biz əmri işlədirik php artisan test yenidən:

 FAIL  Tests\Unit\ExampleTest
⨯ that true is true
 
 FAIL  Tests\Feature\ExampleTest
⨯ the application returns a successful response
 
---
 
• Tests\Unit\ExampleTest > that true is true
Failed asserting that false is true.
 
at tests/Unit/ExampleTest.php:16
   12▕      * @return void
   13▕      */
   14▕     public function test_that_true_is_true()
   15▕     {
➜  16▕         $this->assertTrue(false);
   17▕     }
   18▕ }
   19▕
 
• Tests\Feature\ExampleTest > the application returns a successful response
Expected response status code [200] but received 404.
Failed asserting that 200 is identical to 404.
 
at tests/Feature/ExampleTest.php:19
   15▕     public function test_the_application_returns_a_successful_response()
   16▕     {
   17▕         $response = $this->get('/non-existing-url');
   18▕
➜  19▕         $response->assertStatus(200);
   20▕     }
   21▕ }
   22▕
 
 
Tests:  2 failed
Time:   0.11s

Aşağıda izahatları və uğursuz olan testlərin dəqiq xəttini göstərən oxlarla FAIL kimi qeyd olunan iki uğursuz sınaq var. Səhvlər bu şəkildə göstərilir.

Misal: Laravel-də qeydiyyat forması kodunun sınaqdan keçirilməsi

Tutaq ki, bizim formamız var və biz müxtəlif halları sınaqdan keçirməliyik: onun etibarsız məlumatla uğursuz olub-olmadığını yoxlayırıq, düzgün daxiletmə ilə uğurlu olub-olmadığını yoxlayırıq və s.

Rəsmi başlanğıc dəsti Laravel Breeze tərəfindən daxildir i onun daxilindəki funksionallığın sınaqdan keçirilməsi. Oradan bəzi nümunələrə baxaq:

tests/Feature/RegistrationTest.php

use App\Providers\RouteServiceProvider;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class RegistrationTest extends TestCase
{
    use RefreshDatabase;
 
    public function test_registration_screen_can_be_rendered()
    {
        $response = $this->get('/register');
 
        $response->assertStatus(200);
    }
 
    public function test_new_users_can_register()
    {
        $response = $this->post('/register', [
            'name' => 'Test User',
            'email' => 'test@example.com',
            'password' => 'password',
            'password_confirmation' => 'password',
        ]);
 
        $this->assertAuthenticated();
        $response->assertRedirect(RouteServiceProvider::HOME);
    }
}

Burada bir sinifdə iki testimiz var, çünki onların hər ikisi qeydiyyat forması ilə bağlıdır: biri formanın düzgün yükləndiyini, digəri isə təqdimatın yaxşı işlədiyini yoxlayır.

Nəticəni yoxlamaq üçün daha iki üsulla, daha iki təsdiqlə tanış olaq: $this->assertAuthenticated()$response->assertRedirect(). Rəsmi sənədlərdə mövcud olan bütün iddiaları yoxlaya bilərsiniz PHPUnit e Laravel cavabı . Qeyd edək ki, mövzu ilə bağlı bəzi ümumi iddialar olur $this, digərləri isə xüsusi yoxlayır $responsemarşrut zəngindən.

Başqa bir vacib şeydir use RefreshDatabase;ifadə, vuruşla, sinifin yuxarısına daxil edilir. Test hərəkətləri verilənlər bazasına təsir edə bildikdə lazımdır, bu nümunədə olduğu kimi, giriş qeydinə yeni bir giriş əlavə edir usersverilənlər bazası cədvəli. Bunun üçün yenilənəcək ayrıca test verilənlər bazası yaratmalısınız php artisan migrate:freshhər dəfə testlər keçirilir.

İki seçiminiz var: fiziki olaraq ayrıca verilənlər bazası yaradın və ya yaddaşdaxili SQLite verilənlər bazasından istifadə edin. Hər ikisi faylda konfiqurasiya edilmişdir phpunit.xmldefault olaraq təmin edilirdefinita ilə Laravel. Xüsusilə, bu hissəyə ehtiyacınız var:

<php>
    <env name="APP_ENV" value="testing"/>
    <env name="BCRYPT_ROUNDS" value="4"/>
    <env name="CACHE_DRIVER" value="array"/>
    <!-- <env name="DB_CONNECTION" value="sqlite"/> -->
    <!-- <env name="DB_DATABASE" value=":memory:"/> -->
    <env name="MAIL_MAILER" value="array"/>
    <env name="QUEUE_CONNECTION" value="sync"/>
    <env name="SESSION_DRIVER" value="array"/>
    <env name="TELESCOPE_ENABLED" value="false"/>
</php>

baxın DB_CONNECTIONDB_DATABASEhansılara şərh verilir? Əgər serverinizdə SQLite varsa, ən sadə hərəkət həmin sətirləri sadəcə olaraq şərh etməkdir və testləriniz həmin yaddaşdaxili verilənlər bazasına qarşı işləyəcək.

Bu testdə biz deyirik ki, istifadəçi uğurla autentifikasiya olunub və düzgün ana səhifəyə yönləndirilib, lakin verilənlər bazasında faktiki məlumatları da sınaqdan keçirə bilərik.

Bu koda əlavə olaraq:

$this->assertAuthenticated();
$response->assertRedirect(RouteServiceProvider::HOME);

Biz də istifadə edə bilərik verilənlər bazası test təsdiqləri və belə bir şey edin:

$this->assertDatabaseCount('users', 1);
 
// Or...
$this->assertDatabaseHas('users', [
    'email' => 'test@example.com',
]);

Giriş səhifəsinin nümunəsi

İndi Laravel Breeze ilə Giriş səhifəsinin başqa bir nümunəsinə baxaq

tests/Feature/AuthenticationTest.php:

class AuthenticationTest extends TestCase
{
    use RefreshDatabase;
 
    public function test_login_screen_can_be_rendered()
    {
        $response = $this->get('/login');
 
        $response->assertStatus(200);
    }
 
    public function test_users_can_authenticate_using_the_login_screen()
    {
        $user = User::factory()->create();
 
        $response = $this->post('/login', [
            'email' => $user->email,
            'password' => 'password',
        ]);
 
        $this->assertAuthenticated();
        $response->assertRedirect(RouteServiceProvider::HOME);
    }
 
    public function test_users_can_not_authenticate_with_invalid_password()
    {
        $user = User::factory()->create();
 
        $this->post('/login', [
            'email' => $user->email,
            'password' => 'wrong-password',
        ]);
 
        $this->assertGuest();
    }
}

Söhbət giriş formasından gedir. Məntiq qeydiyyata bənzəyir, elə deyilmi? Ancaq iki əvəzinə üç üsul, buna görə də bu, həm yaxşı, həm də pis ssenariləri sınaqdan keçirmək üçün bir nümunədir. Beləliklə, ümumi məntiq ondan ibarətdir ki, hər iki halı sınamalısınız: işlər yaxşı gedəndə və uğursuz olduqda.

İnnovasiya bülleteni
Yeniliklərlə bağlı ən vacib xəbərləri qaçırmayın. Onları e-poçtla almaq üçün qeydiyyatdan keçin.

Həmçinin, bu testdə gördüyünüz şey istifadəsidir Verilənlər bazası fabrikləri : Laravel saxta istifadəçi yaradır ( yenidən, yenilənmiş test bazanızda ) və sonra düzgün və ya yanlış etimadnamə ilə daxil olmağa çalışır.

Bir daha, Laravel fabriki hazırlayırdefinita üçün yanlış məlumatlarla Usermodel, qutudan kənarda.

database/factories/UserFactory.php:

class UserFactory extends Factory
{
    public function definition()
    {
        return [
            'name' => $this->faker->name(),
            'email' => $this->faker->unique()->safeEmail(),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }
}

Görürsünüzmü, Laravelin özü nə qədər şey hazırlayır, ona görə də sınaqlara başlamaq bizim üçün asan olardı?

Belə ki, biz icra php artisan testLaravel Breeze quraşdırdıqdan sonra belə bir şey görməliyik:

 PASS  Tests\Unit\ExampleTest
✓ that true is true
 
 PASS  Tests\Feature\Auth\AuthenticationTest
✓ login screen can be rendered
✓ users can authenticate using the login screen
✓ users can not authenticate with invalid password
 
 PASS  Tests\Feature\Auth\EmailVerificationTest
✓ email verification screen can be rendered
✓ email can be verified
✓ email is not verified with invalid hash
 
 PASS  Tests\Feature\Auth\PasswordConfirmationTest
✓ confirm password screen can be rendered
✓ password can be confirmed
✓ password is not confirmed with invalid password
 
 PASS  Tests\Feature\Auth\PasswordResetTest
✓ reset password link screen can be rendered
✓ reset password link can be requested
✓ reset password screen can be rendered
✓ password can be reset with valid token
 
 PASS  Tests\Feature\Auth\RegistrationTest
✓ registration screen can be rendered
✓ new users can register
 
 PASS  Tests\Feature\ExampleTest
✓ the application returns a successful response
 
Tests:  17 passed
Time:   0.61s

Vahid testləri və digərləri ilə müqayisədə funksional testlər

Siz alt qovluqları gördünüz tests/Feature e tests/Unit ?. 

Onların arasındakı fərq nədir? 

Qlobal olaraq, Laravel/PHP ekosistemindən kənarda bir neçə növ avtomatlaşdırılmış test mövcuddur. kimi şərtləri tapa bilərsiniz:

  • Vahid sınaqları
  • Xüsusiyyət testi
  • İnteqrasiya testləri
  • Funksional testlər
  • Başdan sona sınaq
  • Qəbul testləri
  • Duman testləri
  • və s.

Mürəkkəb səslənir və bu növ testlər arasındakı faktiki fərqlər bəzən bulanıq olur. Buna görə də Laravel bütün bu dolaşıq terminləri sadələşdirdi və onları iki qrupa ayırdı: vahid/xüsusiyyət.

Sadəcə olaraq, xüsusiyyət testləri tətbiqlərinizin faktiki funksionallığını yerinə yetirməyə çalışır: URL əldə edin, API-yə zəng edin, formanı doldurmaq kimi dəqiq davranışı təqlid edin. Xüsusiyyət testləri adətən hər hansı bir layihə istifadəçisinin real həyatda əl ilə edəcəyi eyni və ya oxşar əməliyyatları yerinə yetirir.

Vahid testlərinin iki mənası var. Ümumiyyətlə, tapa bilərsiniz ki, hər hansı bir avtomatlaşdırılmış test "vahid sınağı" adlanır və bütün prosesi "vahid sınağı" adlandırmaq olar. Lakin funksionallıq və vahid kontekstində bu proses ayrı-ayrılıqda xüsusi qeyri-ictimai kod vahidini sınaqdan keçirməkdən ibarətdir. Məsələn, parametrlərlə ümumi sifariş qiyməti kimi bir şeyi hesablayan metodu olan Laravel sinifiniz var. Buna görə də, vahid testi müxtəlif parametrlərlə həmin metoddan (kod vahidi) düzgün nəticələrin qaytarılıb-qaytarılmadığını bildirir.

Vahid testi yaratmaq üçün bayraq əlavə etməlisiniz:

php artisan make:test OrderPriceTest --unit

Yaradılan kod vahid sınaqdan əvvəlki ilə eynidirdefiLaravel sistemi:

class OrderPriceTest extends TestCase
{
    public function test_example()
    {
        $this->assertTrue(true);
    }
}

Gördüyünüz kimi, mövcud deyil RefreshDatabase, və bu biridir defiƏn çox yayılmış vahid test tərifləri: verilənlər bazasına toxunmur, işləyən proqramdan təcrid olunmuş "qara qutu" kimi işləyir.

Bayaq qeyd etdiyim nümunəni təqlid etməyə çalışaraq, təsəvvür edək ki, bizim xidmət sinfimiz var OrderPrice.

app/Services/OrderPriceService.php:

class OrderPriceService
{
    public function calculatePrice($productId, $quantity, $tax = 0.0)
    {
        // Some kind of calculation logic
    }
}

Sonra vahid testi belə görünə bilər:

class OrderPriceTest extends TestCase
{
    public function test_single_product_no_taxes()
    {
        $product = Product::factory()->create(); // generate a fake product
        $price = (new OrderPriceService())->calculatePrice($product->id, 1);
        $this->assertEquals(1, $price);
    }
 
    public function test_single_product_with_taxes()
    {
        $price = (new OrderPriceService())->calculatePrice($product->id, 1, 20);
        $this->assertEquals(1.2, $price);
    }
 
    // More cases with more parameters
}

Laravel layihələri ilə şəxsi təcrübəmdə testlərin böyük əksəriyyəti Vahid testləri deyil, Xüsusiyyət testləridir. Əvvəlcə tətbiqinizin işlədiyini, real insanların ondan necə istifadə edəcəyini yoxlamaq lazımdır.

Sonra, xüsusi hesablamalarınız və ya məntiqiniz varsa, edə bilərsiniz definire bir vahid olaraq, parametrlərlə, bunun üçün xüsusi olaraq vahid testləri yarada bilərsiniz.

Bəzən testlərin yazılması kodun özünü dəyişdirməyi və onu daha “sınaq edilə bilən” etmək üçün refaktorinq etməyi tələb edir: bölmələri xüsusi siniflərə və ya metodlara ayırmaq.

Testləri nə vaxt/necə etmək lazımdır?

Bunun faktiki istifadəsi nədir php artisan test, nə vaxt işlətməlisiniz?

Biznesinizin iş axınından asılı olaraq müxtəlif yanaşmalar var, lakin son kod dəyişikliklərini anbara köçürməzdən əvvəl ümumiyyətlə bütün testlərin “yaşıl” (yəni xətasız) olmasını təmin etməlisiniz.

Sonra tapşırığınızın üzərində yerli olaraq işləyirsiniz və işinizi bitirdiyinizi düşündüyünüz zaman heç nəyi pozmadığınızdan əmin olmaq üçün bəzi testlər keçirin. Unutmayın ki, kodunuz təkcə məntiqinizdə səhvlərə səbəb ola bilər, həm də başqasının çoxdan yazılmış kodunda istər-istəməz başqa davranışı poza bilər.

Bir az da irəli getsək, avtomatlaşdırmaq olar çoxlu şeylər. Müxtəlif CI/CD alətləri ilə, kimsə müəyyən bir Git filialına dəyişikliklər etdikdə və ya kodu istehsal bölməsinə birləşdirməzdən əvvəl yerinə yetiriləcək testləri təyin edə bilərsiniz. Ən sadə iş axını Github Actions-dan istifadə etmək olardı, məndə var ayrı bir video bunu sübut edən.

Nə test etməlisiniz?

"Test əhatəsi" adlanan şeyin nə qədər böyük olması ilə bağlı müxtəlif fikirlər var: hər səhifədə mümkün olan hər əməliyyatı və işi sınayın və ya işi ən vacib hissələrlə məhdudlaşdırın.

Əslində, mən avtomatlaşdırılmış testi faktiki fayda verməkdən daha çox vaxt almaqda ittiham edən insanlarla razılaşdığım yerdir. Hər bir detal üçün testlər yazsanız, bu baş verə bilər. Bu, layihəniz tərəfindən tələb oluna bilər: əsas sual "potensial səhvin qiyməti nədir".

Başqa sözlə, “Bu kod uğursuz olarsa, nə baş verərdi?” sualını verməklə sınaq səylərinizi prioritetləşdirməlisiniz. Ödəniş sisteminizdə səhvlər varsa, bu, biznesə birbaşa təsir edəcək. Beləliklə, əgər rollarınızın/icazələrinizin funksionallığı pozulubsa, bu, böyük bir təhlükəsizlik problemidir.

Mett Staufferin konfransda dediyi sözləri bəyənirəm: "Əvvəlcə uğursuz olarsa, işinizdən qovulmağınıza səbəb olacaq şeyləri sınaqdan keçirməlisiniz." Əlbəttə ki, bu, mübaliğədir, amma siz fikirləşirsiniz: əvvəlcə vacib olanı sınayın. Və sonra digər xüsusiyyətlər, əgər vaxtınız varsa.

PEST: PHPUnit-ə yeni alternativ

Yuxarıdakı bütün nümunələr Laravel öncəsi sınaq alətinə əsaslanırdefigecə: PHPUnit . Lakin illər keçdikcə ekosistemdə başqa alətlər meydana çıxdı və ən son məşhur olanlardan biri də belədir Zərərverici . Rəsmi Laravel işçisi tərəfindən yaradılmışdır Nuno Maduro , sintaksisi sadələşdirməyi, testlər üçün kodu daha da sürətli yazmağı hədəfləyir.

Başlıq altında, qaçır su PHPUnit, əlavə bir təbəqə olaraq, sadəcə bəzi əvvəlcədən təkrarlanan hissələri minimuma endirməyə çalışırdefiPHPUnit kodunun son nöqtəsi.

Bir nümunəyə baxaq. Ön xüsusiyyət test sinifini xatırlayındefiLaraveldə nited? Sizə xatırladacağam:

namespace Tests\Feature;
 
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
    public function test_the_application_returns_a_successful_response()
    {
        $response = $this->get('/');
 
        $response->assertStatus(200);
    }
}

Eyni testin PEST ilə necə görünəcəyini bilirsinizmi?

test('the application returns a successful response')->get('/')->assertStatus(200);

Bəli, BİR sətir kod və bu qədər. Beləliklə, PEST-in məqsədi aşağıdakıları aradan qaldırmaqdır:

  • Hər şey üçün siniflər və metodlar yaratmaq;
  • Test işinin uzadılması;
  • Fəaliyyətləri ayrı-ayrı sətirlərə qoymaqla: PEST-də onları bir-birinə bağlaya bilərsiniz.

Laravel-də PEST testi yaratmaq üçün əlavə bayraq göstərməlisiniz:

php artisan make:test HomepageTest --pest

Bu yazıya görə, PEST Laravel tərtibatçıları arasında olduqca populyardır, lakin bu əlavə alətdən istifadə edib onun sintaksisini, həmçinin PHPUnit qeydini öyrənmək sizin şəxsi seçiminizdir.

BlogInnovazione.it

İnnovasiya bülleteni
Yeniliklərlə bağlı ən vacib xəbərləri qaçırmayın. Onları e-poçtla almaq üçün qeydiyyatdan keçin.

Articoli recenti

Catania Poliklinikasında Apple tamaşaçısı ilə Artırılmış Reallığa innovativ müdaxilə

Kataniya poliklinikasında Apple Vision Pro kommersiya görüntüləyicisi ilə oftalmoplastika əməliyyatı həyata keçirilib...

3 May 2024

Uşaqlar üçün Boyama Səhifələrinin Faydaları - bütün yaşlar üçün sehrli bir dünya

Rəngləmə yolu ilə incə motor bacarıqlarının inkişafı uşaqları yazı kimi daha mürəkkəb bacarıqlara hazırlayır. Rəngləmək üçün…

2 May 2024

Gələcək buradadır: Gəmiçilik Sənayesi Qlobal İqtisadiyyatda Necə inqilab edir

Dəniz sektoru 150 milyardlıq bazara doğru irəliləyən əsl qlobal iqtisadi gücdür...

1 May 2024

Nəşriyyatçılar və OpenAI süni intellekt tərəfindən işlənmiş məlumat axınını tənzimləmək üçün müqavilələr imzalayırlar.

Keçən bazar ertəsi Financial Times OpenAI ilə müqavilə elan etdi. FT dünya səviyyəli jurnalistikasına lisenziya verir...

30 Aprel 2024