Артыкулы

Даведайцеся, як рабіць тэсты ў Laravel на простых прыкладах, выкарыстоўваючы PHPUnit і PEST

Калі справа даходзіць да аўтаматызаваных тэстаў або модульных тэстаў, у любой мове праграмавання ёсць два супрацьлеглыя меркаванні:

  • Марнаванне часу
  • Без гэтага не абыдзешся

Такім чынам, у гэтым артыкуле мы паспрабуем пераканаць першага, асабліва прадэманстраваўшы, як лёгка пачаць аўтаматызаванае тэсціраванне ў Laravel.

Спачатку давайце пагаворым пра тое, "чаму", а потым паглядзім некалькі прыкладаў таго, як.

Навошта нам патрэбна аўтаматызаванае тэставанне

Аўтаматызаваныя тэсты запускаюць часткі кода і паведамляюць аб любых памылках. Гэта самы просты спосаб іх апісаць. Уявіце сабе, што вы запускаеце новую функцыю ў дадатку, а потым персанальны памочнік-робат пойдзе і ўручную праверыць новую функцыю, адначасова правяраючы, ці не парушае новы код якую-небудзь са старых функцый.

Гэта галоўная перавага: аўтаматычнае паўторнае тэставанне ўсіх функцый. Гэта можа здацца дадатковай працай, але калі вы не загадаеце «робату» зрабіць гэта, мы павінны зрабіць гэта ўручную, так? 

Або новыя функцыі могуць быць выпушчаны без праверкі іх працы, спадзеючыся, што карыстальнікі будуць паведамляць пра памылкі.

Аўтаматызаваныя тэсты могуць даць нам некалькі пераваг:

  • Эканомія часу ручнога тэставання;
  • Яны дазваляюць зэканоміць час як на новай рэалізаванай функцыі, так і на кансалідаваных функцыях, пазбягаючы рэгрэсіі;
  • Памножце гэтую выгаду на ўсе новыя функцыі і ўсе функцыі, якія ўжо рэалізаваны;
  • Папярэднія тры пункты прымяняюцца да кожнай новай версіі;
  • ...

Паспрабуйце ўявіць сваю праграму праз год ці два з новымі распрацоўшчыкамі ў камандзе, якія не ведаюць кода, напісанага ў папярэднія гады, і нават таго, як яго тэставаць. 

Нашы першыя аўтаматызаваныя тэсты

Каб выканаць першае аўтаматызаванае тэсціраванне ў Laravel, вам не трэба пісаць код. Так, вы правільна прачыталі. Усё ўжо настроена і падрыхтавана ў перадусталёўцыdefiканец Laravel, уключаючы самы першы асноўны прыклад.

Вы можаце паспрабаваць усталяваць праект Laravel і неадкладна запусціць першыя тэсты:

laravel new project
cd project
php artisan test

Гэта павінен быць вынік у вашай кансолі:

Калі мы паглядзім на прэdefiканец Laravel /tests, у нас ёсць два файла:

тэсты/Feature/ExampleTest.php :

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

Вам не трэба ведаць сінтаксіс, каб зразумець, што тут адбываецца: загрузіце галоўную старонку і праверце, ці код стану HTTP і "200 OK».

Таксама вядомы як назва метаду test_the_application_returns_a_successful_response() становіцца чытэльным тэкстам, калі вы праглядаеце вынікі тэсту, проста замяніўшы сімвал падкрэслівання прабелам.

тэсты/Unit/ExampleTest.php :

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

Здаецца, бессэнсоўна правяраць, ці праўда гэта? 

Пра модульныя тэсты мы пагаворым крыху пазней. На дадзены момант вам трэба зразумець, што звычайна адбываецца ў кожным тэсце.

  • Кожны тэставы файл у тэчцы /tests гэта клас PHP, які пашырае TestCase PHPUnit
  • Унутры кожнага класа вы можаце стварыць некалькі метадаў, звычайна адзін метад для сітуацыі для тэставання
  • У рамках кожнага метаду ёсць тры дзеянні: падрыхтоўка сітуацыі, затым прыняцце дзеянняў і затым праверка (пацвярджэнне), ці адпавядае вынік чаканням

Структурна гэта ўсё, што вам трэба ведаць, усё астатняе залежыць ад канкрэтных рэчаў, якія вы хочаце праверыць.

Каб стварыць пусты тэставы клас, проста выканайце наступную каманду:

php artisan make:test HomepageTest

Файл згенераваны 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);
    }
}

Зараз давайце паглядзім, што адбудзецца, калі тэставы код не працуе ў Laravel

Давайце цяпер паглядзім, што адбудзецца, калі тэставыя зацвярджэнні не вернуць чаканага выніку.

Давайце зменім прыклады тэстаў на гэта:

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);
    }
}

А цяпер, калі мы запусцім каманду php artisan test зноў:

 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

Ёсць два няўдалыя тэсты, пазначаныя як НЯМАЛЬНА, з тлумачэннямі ніжэй і стрэлкамі, якія паказваюць на дакладны радок няўдалых тэстаў. Памылкі пазначаюцца такім чынам.

Прыклад: тэставанне кода рэгістрацыйнай формы ў Laravel

Выкажам здагадку, што ў нас ёсць форма, і нам трэба праверыць розныя выпадкі: мы правяраем, ці не атрымліваецца яна з няправільнымі дадзенымі, мы правяраем, ці атрымліваецца яна з правільным уводам і г.д.

Афіцыйны стартавы набор ад Laravel Breeze уключае я тэставанне яго функцыянальнасці. Давайце паглядзім некалькі прыкладаў адтуль:

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);
    }
}

Тут у нас ёсць два тэсты ў адным класе, паколькі яны абодва звязаны з формай рэгістрацыі: адзін правярае, ці правільна загружана форма, а другі правярае, ці правільна працуе заяўка.

Азнаёмімся яшчэ з двума метадамі праверкі выніку, яшчэ двума сцвярджэннямі: $this->assertAuthenticated()$response->assertRedirect(). Вы можаце праверыць усе сцвярджэнні, даступныя ў афіцыйнай дакументацыі PHPUnit e Адказ Laravel . Звярніце ўвагу, што на гэтую тэму сустракаюцца некаторыя агульныя сцвярджэнні $this, а іншыя правяраюць канкрэтныя $responseз маршрутнага выкліку.

Іншая важная рэч - гэта use RefreshDatabase;заява, з рыскай, устаўленай над класам. Гэта неабходна, калі тэставыя дзеянні могуць паўплываць на базу дадзеных, як у гэтым прыкладзе, вядзенне часопіса дадае новы запіс у usersтабліца базы дадзеных. Для гэтага неабходна стварыць асобную тэставую базу дадзеных, якая будзе абнаўляцца php artisan migrate:freshкожны раз, калі запускаюцца тэсты.

У вас ёсць два варыянты: фізічна стварыць асобную базу дадзеных або выкарыстоўваць базу дадзеных SQLite ў памяці. Абодва настроены ў файле phpunit.xmlпрадугледжана па змаўчанніdefiНіта с Laravel. У прыватнасці, вам патрэбна гэтая частка:

<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>

Глядзіце DB_CONNECTIONDB_DATABASEякія з іх каментуюцца? Калі ў вас ёсць SQLite на вашым серверы, самае простае дзеянне - проста раскаментаваць гэтыя радкі, і вашыя тэсты будуць працаваць з гэтай базай дадзеных у памяці.

У гэтым тэсце мы кажам, што карыстальнік паспяхова аўтэнтыфікаваны і перанакіраваны на правільную хатнюю старонку, але мы таксама можам праверыць фактычныя даныя ў базе дадзеных.

У дадатак да гэтага кода:

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

Мы таксама можам выкарыстоўваць тэставыя зацвярджэння базы дадзеных і зрабіць нешта накшталт гэтага:

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

Прыклад старонкі ўваходу

Давайце зараз паглядзім іншы прыклад старонкі ўваходу ў Laravel Breeze

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();
    }
}

Гаворка ідзе пра форму ўваходу. Логіка падобная на рэгістрацыю, так? Але тры метады замест двух, таму гэта прыклад праверкі як добрых, так і дрэнных сцэнарыяў. Такім чынам, звычайная логіка заключаецца ў тым, што вы павінны праверыць абодва выпадкі: калі справы ідуць добра і калі не.

Інавацыйны бюлетэнь
Не прапусціце самыя важныя навіны пра інавацыі. Падпішыцеся, каб атрымліваць іх па электроннай пошце.

Акрамя таго, тое, што вы бачыце ў гэтым тэсце, - гэта выкарыстанне Фабрыкі баз дадзеных : Laravel стварае фальшывага карыстальніка ( зноў жа, у вашай абноўленай тэставай базе дадзеных ), а потым спрабуе ўвайсці з правільнымі або няправільнымі ўліковымі дадзенымі.

У чарговы раз Laravel стварае фабрычны папярэдні файлdefinita з ілжывымі дадзенымі для Userмадэль, нестандартна.

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),
        ];
    }
}

Разумееце, колькі рэчаў падрыхтавана самім Laravel, ці лёгка нам было б пачаць тэсціраванне?

Такім чынам, калі мы выканаем php artisan testпасля ўстаноўкі Laravel Breeze мы павінны ўбачыць нешта накшталт гэтага:

 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

Функцыянальныя тэсты ў параўнанні з модульнымі тэстамі і іншымі

Вы бачылі падпапкі tests/Feature e tests/Unit ?. 

У чым розніца паміж імі? 

Ва ўсім свеце, па-за экасістэмай Laravel/PHP, існуе некалькі тыпаў аўтаматызаванага тэсціравання. Вы можаце знайсці такія тэрміны, як:

  • Адзінкавыя тэсты
  • Тэставанне функцый
  • Інтэграцыйныя тэсты
  • Функцыянальныя тэсты
  • Скразное тэставанне
  • Прыёмачныя выпрабаванні
  • Дымавыя выпрабаванні
  • г.д.

Гэта гучыць складана, і рэальныя адрозненні паміж гэтымі тыпамі тэстаў часам размытыя. Вось чаму Laravel спрасціў усе гэтыя заблытаныя тэрміны і згрупаваў іх у два: адзінка/функцыя.

Прасцей кажучы, тэсты функцый спрабуюць выканаць фактычную функцыянальнасць вашых прыкладанняў: атрымаць URL, выклікаць API, імітаваць дакладныя паводзіны, напрыклад, запаўненне формы. Тэсты функцый звычайна выконваюць тыя ж або падобныя аперацыі, што і любы карыстальнік праекта ўручную ў рэальным жыцці.

Адзінкавыя тэсты маюць два значэнні. Увогуле, вы можаце выявіць, што любы аўтаматызаваны тэст называецца «модульным тэсціраваннем», а ўвесь працэс можна назваць «модульным тэсціраваннем». Але ў кантэксце функцыянальнасці супраць блока, гэты працэс звязаны з тэставаннем пэўнай непублічнай адзінкі кода ў ізаляцыі. Напрыклад, у вас ёсць клас Laravel з метадам, які нешта вылічае, напрыклад, агульную цану замовы з параметрамі. Такім чынам, модульны тэст будзе паказваць, ці правільныя вынікі вяртаюцца з гэтага метаду (кодавай адзінкі) з іншымі параметрамі.

Каб стварыць модульны тэст, вам трэба дадаць сцяг:

php artisan make:test OrderPriceTest --unit

Згенераваны код такі ж, як і перад модульным тэстамdefiСістэма Laravel:

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

Як бачыце, яго не існуе RefreshDatabase, і гэта адзін з defiнайбольш распаўсюджаныя азначэнні модульнага тэсту: ён не закранае базу дадзеных, ён працуе як «чорная скрыня», ізаляваная ад запушчанага прыкладання.

Спрабуючы пераймаць прыклад, які я згадваў раней, давайце ўявім, што ў нас ёсць клас абслугоўвання OrderPrice.

app/Services/OrderPriceService.php:

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

Тады модульны тэст можа выглядаць прыкладна так:

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, пераважная большасць тэстаў - гэта тэсты функцый, а не модульныя тэсты. Па-першае, вам трэба праверыць, ці працуе ваша прыкладанне так, як ім карысталіся б рэальныя людзі.

Далей, калі ў вас ёсць спецыяльныя разлікі або логіка, вы можаце definire як адзінка, з параметрамі, вы можаце ствараць модульныя тэсты спецыяльна для гэтага.

Часам напісанне тэстаў патрабуе мадыфікацыі самога кода і яго рэфактарынгу, каб зрабіць яго больш «тэсціраваным»: раздзяленне адзінак на спецыяльныя класы або метады.

Калі/як праводзіць тэсты?

Якая сапраўдная карысць ад гэтага php artisan test, калі вы павінны запусціць яго?

Існуюць розныя падыходы ў залежнасці ад працоўнага працэсу вашага бізнесу, але звычайна вам трэба пераканацца, што ўсе тэсты з'яўляюцца «эканомнымі» (г.зн. без памылак), перш чым адпраўляць канчатковыя змены кода ў рэпазітар.

Затым вы працуеце над сваёй задачай лакальна, і калі лічыце, што скончылі, запусціце некаторыя тэсты, каб пераканацца, што вы нічога не зламалі. Памятайце, што ваш код можа выклікаць памылкі не толькі ў вашай логіцы, але і ненаўмысна парушыць некаторыя іншыя паводзіны ў чужым кодзе, напісаным даўно.

Калі мы зробім крок наперад, гэта магчыма аўтаматызаваць многія рэчы. З дапамогай розных інструментаў CI/CD вы можаце вызначыць тэсты, якія будуць запускацца кожны раз, калі хтосьці ўносіць змены ў пэўную галінку Git або перад аб'яднаннем кода ў галіну вытворчасці. Самым простым працоўным працэсам было б выкарыстоўваць Github Actions, у мяне ёсць асобнае відэа што даказвае гэта.

Што трэба праверыць?

Існуюць розныя меркаванні наконт таго, наколькі вялікім павінен быць так званы «тэставы ахоп»: паспрабаваць усе магчымыя аперацыі і выпадкі на кожнай старонцы або абмежаваць працу найбольш важнымі часткамі.

Фактычна, тут я згодны з людзьмі, якія абвінавачваюць аўтаматызаванае тэсціраванне ў тым, што яно займае больш часу, чым прыносіць рэальную карысць. Гэта можа адбыцца, калі вы пішаце тэсты для кожнай дэталі. Тым не менш, гэта можа спатрэбіцца вашаму праекту: галоўнае пытанне - "якая цана патэнцыйнай памылкі".

Іншымі словамі, вам трэба расставіць прыярытэты ў вашых намаганнях па тэсціраванні, задаючы пытанне: «Што будзе, калі гэты код не атрымаецца?» Калі ў вашай плацежнай сістэме ёсць памылкі, гэта непасрэдна паўплывае на бізнес. Такім чынам, калі функцыянальнасць вашых роляў/дазволаў парушана, гэта вялізная праблема бяспекі.

Мне падабаецца, як сказаў Мэт Стауфер на канферэнцыі: «Вы павінны спачатку праверыць тыя рэчы, якія, калі яны не атрымаюцца, прывядуць да звальнення з працы». Вядома, гэта перабольшанне, але вы зразумелі: спачатку паспрабуйце важныя рэчы. А потым іншыя функцыі, калі ў вас ёсць час.

PEST: новая альтэрнатыва PHPUnit

Усе прыведзеныя вышэй прыклады заснаваны на інструменце папярэдняга тэставання Laraveldefiноч: PHPUnit . Але з гадамі ў экасістэме з'явіліся іншыя інструменты, і адзін з апошніх папулярных ШКОДНІК . Створана афіцыйным супрацоўнікам Laravel Нуну Мадура , накіраваны на спрашчэнне сінтаксісу, што робіць напісанне кода для тэстаў яшчэ больш хуткім.

Пад капотам ён працуе su PHPUnit, як дадатковы ўзровень, проста спрабуе мінімізаваць некаторыя папярэдне паўтораныя часткіdefiканец кода PHPUnit.

Давайце паглядзім на прыкладзе. Запомніце папярэдні клас тэсціравання функцыйdefiу Laravel? Нагадаю:

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);
    }
}

Ці ведаеце вы, як будзе выглядаць той самы тэст з PEST?

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

Так, АДЗІН радок кода і ўсё. Такім чынам, мэта PEST - выдаліць накладныя выдаткі на:

  • Стварэнне класаў і метадаў для ўсяго;
  • Пашырэнне тэставага выпадку;
  • Размяшчаючы дзеянні ў асобных радках: у PEST вы можаце злучыць іх разам.

Каб згенераваць PEST-тэст у Laravel, вам неабходна ўказаць дадатковы сцяг:

php artisan make:test HomepageTest --pest

На момант напісання гэтага артыкула PEST даволі папулярны сярод распрацоўшчыкаў Laravel, але карыстацца гэтым дадатковым інструментам і вывучаць яго сінтаксіс, а таксама заўвагу PHPUnit вырашаць вам асабіста.

BlogInnovazione.it

Інавацыйны бюлетэнь
Не прапусціце самыя важныя навіны пра інавацыі. Падпішыцеся, каб атрымліваць іх па электроннай пошце.

Апошнія артыкулы

Новы штучны інтэлект Google можа мадэляваць ДНК, РНК і «ўсе малекулы жыцця»

Google DeepMind прадстаўляе палепшаную версію сваёй мадэлі штучнага інтэлекту. Новая ўдасканаленая мадэль забяспечвае не толькі...

9 мая 2024

Вывучэнне модульнай архітэктуры Laravel

Laravel, вядомы сваім элегантным сінтаксісам і магутнымі функцыямі, таксама забяспечвае трывалую аснову для модульнай архітэктуры. Там…

9 мая 2024

Cisco Hypershield і набыццё Splunk Пачынаецца новая эра бяспекі

Cisco і Splunk дапамагаюць кліентам паскорыць іх шлях да Аперацыйнага цэнтра бяспекі (SOC) будучыні з дапамогай…

8 мая 2024

Акрамя эканамічнага боку: невідавочны кошт праграм-вымагальнікаў

Праграмы-вымагальнікі дамінавалі ў навінах апошнія два гады. Большасць людзей добра ведаюць, што напады...

6 мая 2024

Інавацыйнае ўмяшанне ў дапоўненую рэальнасць з праграмай прагляду Apple у паліклініцы Катаніі

У паліклініцы Катаніі праведзена аперацыя афтальмапластыкі з выкарыстаннем камерцыйнай праграмы прагляду Apple Vision Pro…

3 мая 2024

Перавагі размалёвак для дзяцей - свет чараўніцтва для ўсіх узростаў

Развіццё дробнай маторыкі з дапамогай размалёўкі рыхтуе дзяцей да больш складаных навыкаў, такіх як пісьмо. Размаляваць…

2 мая 2024

Будучыня тут: як індустрыя суднаходства рэвалюцыянізуе сусветную эканоміку

Ваенна-марскі сектар - гэта сапраўдная глабальная эканамічная сіла, якая перайшла да 150-мільярднага рынку...

1 мая 2024

Выдаўцы і OpenAI падпісваюць пагадненні аб рэгуляванні патоку інфармацыі, апрацаванай штучным інтэлектам

У мінулы панядзелак Financial Times абвясціла аб здзелцы з OpenAI. FT ліцэнзуе сваю журналістыку сусветнага ўзроўню...

Красавік 30 2024

Чытайце Innovation на сваёй мове

Інавацыйны бюлетэнь
Не прапусціце самыя важныя навіны пра інавацыі. Падпішыцеся, каб атрымліваць іх па электроннай пошце.

Выконвайце за намі