Daripada PHPUnit ke Go: Ujian Unit Terpacu Data untuk Pembangun Go

Patricia Arquette
Lepaskan: 2024-11-12 19:21:02
asal
240 orang telah melayarinya

From PHPUnit to Go: Data-Driven Unit Testing for Go Developers

Dalam siaran ini, kami akan meneroka cara membawa minda ujian unit PHP, terutamanya pendekatan penyedia data rangka kerja PHPUnit, ke dalam Go. Jika anda seorang pembangun PHP yang berpengalaman, anda mungkin biasa dengan model pembekal data: mengumpulkan data ujian secara berasingan dalam tatasusunan mentah dan memasukkan data ini ke dalam fungsi ujian. Pendekatan ini menjadikan ujian unit lebih bersih, lebih boleh diselenggara dan mematuhi prinsip seperti Terbuka/Tertutup.

Mengapa pendekatan pembekal data?

Menggunakan pendekatan penyedia data untuk menstruktur ujian unit dalam Go memberikan beberapa kelebihan, termasuk:

Kebolehbacaan dan Kebolehlanjutan Dipertingkat: Ujian menjadi teratur secara visual, dengan tatasusunan yang dipisahkan dengan jelas di bahagian atas mewakili setiap senario ujian. Setiap kunci tatasusunan menerangkan senario, manakala kandungannya memegang data untuk menguji senario tersebut. Struktur ini menjadikan fail senang dikerjakan dan mudah dipanjangkan.

Pengasingan Kebimbangan: Model pembekal data menyimpan data dan logik ujian, menghasilkan fungsi yang ringan dan dipisahkan yang sebahagian besarnya boleh kekal tidak berubah dari semasa ke semasa. Menambah senario baharu hanya memerlukan penambahan lebih banyak data kepada pembekal, memastikan fungsi ujian terbuka untuk sambungan tetapi ditutup untuk pengubahsuaian—aplikasi praktikal Prinsip Terbuka/Tertutup dalam ujian.

Dalam sesetengah projek, saya juga pernah melihat senario yang cukup padat untuk menjamin penggunaan fail JSON yang berasingan sebagai sumber data, dibina secara manual dan disalurkan kepada pembekal, yang seterusnya membekalkan data kepada fungsi ujian.

Bilakah sangat digalakkan untuk menggunakan pembekal data?

Penggunaan penyedia data amat digalakkan apabila anda mempunyai sejumlah besar kes ujian dengan data yang berbeza-beza: setiap kes ujian adalah sama secara konsep tetapi berbeza hanya dalam input dan output yang dijangkakan.

Menggabungkan data dan logik dalam satu fungsi ujian boleh mengurangkan Pengalaman Pembangun (DX). Ia selalunya membawa kepada:

Verbosity Overload: Kod berlebihan yang mengulangi pernyataan dengan sedikit variasi data, yang membawa kepada pangkalan kod yang bertele-tele tanpa faedah tambahan.

Kejelasan yang Dikurangkan: Mengimbas melalui fungsi ujian menjadi tugasan apabila cuba mengasingkan data ujian sebenar daripada kod sekeliling, yang mana pendekatan pembekal data secara semulajadi mengurangkannya.

Bagus, jadi apakah sebenarnya pembekal data?

Corak DataProvider dalam PHPUnit di mana pada asasnya fungsi pembekal membekalkan fungsi ujian dengan set data berbeza yang digunakan dalam gelung tersirat. Ia memastikan prinsip DRY (Don't Repeat Yourself) dan sejajar dengan Prinsip Terbuka/Tertutup juga, dengan memudahkan untuk menambah atau mengubah suai senario ujian tanpa mengubah logik fungsi ujian teras.

Menyelesaikan masalah tanpa pembekal data?

Untuk menggambarkan kelemahan verbositi, pertindihan kod dan cabaran penyelenggaraan, berikut ialah coretan contoh ujian unit untuk fungsi isihan gelembung tanpa bantuan penyedia data:

<?php

declare(strict_types=1);

use PHPUnit\Framework\TestCase;

final class BubbleSortTest extends TestCase
{
    public function testBubbleSortEmptyArray()
    {
        $this->assertSame([], BubbleSort([]));
    }

    public function testBubbleSortOneElement()
    {
        $this->assertSame([0], BubbleSort([0]));
    }

    public function testBubbleSortTwoElementsSorted()
    {
        $this->assertSame([5, 144], BubbleSort([5, 144]));
    }

    public function testBubbleSortTwoElementsUnsorted()
    {
        $this->assertSame([-7, 10], BubbleSort([10, -7]));
    }

    public function testBubbleSortMultipleElements()
    {
        $this->assertSame([1, 2, 3, 4], BubbleSort([1, 3, 4, 2]));
    }

    // And so on for each test case, could be 30 cases for example.

    public function testBubbleSortDescendingOrder()
    {
        $this->assertSame([1, 2, 3, 4, 5], BubbleSort([5, 4, 3, 2, 1]));
    }

    public function testBubbleSortBoundaryValues()
    {
        $this->assertSame([-2147483647, 2147483648], BubbleSort([2147483648, -2147483647]));
    }
}

Salin selepas log masuk

Adakah terdapat masalah dengan kod di atas? pasti:

Verbosity: Setiap kes ujian memerlukan kaedah yang berasingan, menghasilkan asas kod berulang yang besar.

Penduaan: Logik ujian diulang dalam setiap kaedah, hanya berbeza mengikut input dan output yang dijangkakan.

Pelanggaran Terbuka/Tertutup: Menambah kes ujian baharu memerlukan mengubah struktur kelas ujian dengan mencipta lebih banyak kaedah.

Menyelesaikan masalah dengan pembekal data!

Berikut ialah suite ujian yang sama yang difaktorkan semula untuk menggunakan pembekal data

<?php

declare(strict_types=1);

use PHPUnit\Framework\TestCase;

final class BubbleSortTest extends TestCase
{
    /**
     * Provides test data for bubble sort algorithm.
     *
     * @return array<string, array>
     */
    public function bubbleSortDataProvider(): array
    {
        return [
            'empty' => [[], []],
            'oneElement' => [[0], [0]],
            'twoElementsSorted' => [[5, 144], [5, 144]],
            'twoElementsUnsorted' => [[10, -7], [-7, 10]],
            'moreThanOneElement' => [[1, 3, 4, 2], [1, 2, 3, 4]],
            'moreThanOneElementWithRepetition' => [[1, 4, 4, 2], [1, 2, 4, 4]],
            'moreThanOneElement2' => [[7, 7, 1, 0, 99, -5, 10], [-5, 0, 1, 7, 7, 10, 99]],
            'sameElement' => [[1, 1, 1, 1], [1, 1, 1, 1]],
            'negativeNumbers' => [[-5, -2, -10, -1, -3], [-10, -5, -3, -2, -1]],
            'descendingOrder' => [[5, 4, 3, 2, 1], [1, 2, 3, 4, 5]],
            'randomOrder' => [[9, 2, 7, 4, 1, 6, 3, 8, 5], [1, 2, 3, 4, 5, 6, 7, 8, 9]],
            'duplicateElements' => [[2, 2, 1, 1, 3, 3, 4, 4], [1, 1, 2, 2, 3, 3, 4, 4]],
            'largeArray' => [[-1, -10000, -12345, -2032, -23, 0, 0, 0, 0, 10, 10000, 1024, 1024354, 155, 174, 1955, 2, 255, 3, 322, 4741, 96524], [-1, -10000, -12345, -2032, -23, 0, 0, 0, 0, 10, 10000, 1024, 1024354, 155, 174, 1955, 2, 255, 3, 322, 4741, 96524]],
            'singleNegativeElement' => [[-7], [-7]],
            'arrayWithZeroes' => [[0, -2, 0, 3, 0], [-2, 0, 0, 0, 3]],
            'ascendingOrder' => [[1, 2, 3, 4, 5], [1, 2, 3, 4, 5]],
            'descendingOrderWithDuplicates' => [[5, 5, 4, 3, 3, 2, 1], [1, 2, 3, 3, 4, 5, 5]],
            'boundaryValues' => [[2147483648, -2147483647], [-2147483647, 2147483648]],
            'mixedSignNumbers' => [[-1, 0, 1, -2, 2], [-2, -1, 0, 1, 2]],
        ];
    }

    /**
     * @dataProvider bubbleSortDataProvider
     *
     * @param array<int> $input
     * @param array<int> $expected
     */
    public function testBubbleSort(array $input, array $expected)
    {
        $this->assertSame($expected, BubbleSort($input));
    }
}

Salin selepas log masuk

Adakah terdapat sebarang kelebihan menggunakan pembekal data? oh ya:

Keringkas: Semua data ujian dipusatkan dalam satu kaedah, menghilangkan keperluan untuk berbilang fungsi untuk setiap senario.

Kebolehbacaan Dipertingkat: Setiap kes ujian disusun dengan baik, dengan kunci deskriptif untuk setiap senario.

Prinsip Terbuka/Tertutup: Kes baharu boleh ditambahkan pada pembekal data tanpa mengubah logik ujian teras.

DX (Pengalaman Pembangun) yang Dipertingkatkan: Struktur ujian bersih, menarik perhatian, menjadikan pembangun yang malas itu terdorong untuk melanjutkan, nyahpepijat atau mengemas kininya.

Membawa Penyedia Data untuk Pergi

  • Go tidak mempunyai model pembekal data asli seperti PHPUnit, jadi kami perlu menggunakan pendekatan yang berbeza. Mungkin terdapat banyak pelaksanaan dengan beberapa tahap kerumitan, berikut adalah purata yang mungkin menjadi calon untuk mensimulasikan penyedia data di Go land
package sort

import (
    "testing"

    "github.com/stretchr/testify/assert"
)

type TestData struct {
    ArrayList    map[string][]int
    ExpectedList map[string][]int
}

const (
    maxInt32 = int32(^uint32(0) >> 1)
    minInt32 = -maxInt32 - 1
)

var testData = &TestData{
    ArrayList: map[string][]int{
        "empty":                            {},
        "oneElement":                       {0},
        "twoElementsSorted":                {5, 144},
        "twoElementsUnsorted":              {10, -7},
        "moreThanOneElement":               {1, 3, 4, 2},
        "moreThanOneElementWithRepetition": {1, 4, 4, 2},
        "moreThanOneElement2":              {7, 7, 1, 0, 99, -5, 10},
        "sameElement":                      {1, 1, 1, 1},
        "negativeNumbers":                  {-5, -2, -10, -1, -3},
        "descendingOrder":                  {5, 4, 3, 2, 1},
        "randomOrder":                      {9, 2, 7, 4, 1, 6, 3, 8, 5},
        "duplicateElements":                {2, 2, 1, 1, 3, 3, 4, 4},
        "largeArray":                       {-1, -10000, -12345, -2032, -23, 0, 0, 0, 0, 10, 10000, 1024, 1024354, 155, 174, 1955, 2, 255, 3, 322, 4741, 96524},
        "singleNegativeElement":            {-7},
        "arrayWithZeroes":                  {0, -2, 0, 3, 0},
        "ascendingOrder":                   {1, 2, 3, 4, 5},
        "descendingOrderWithDuplicates":    {5, 5, 4, 3, 3, 2, 1},
        "boundaryValues":                   {2147483648, -2147483647},
        "mixedSignNumbers":                 {-1, 0, 1, -2, 2},
    },
    ExpectedList: map[string][]int{
        "empty":                            {},
        "oneElement":                       {0},
        "twoElementsSorted":                {5, 144},
        "twoElementsUnsorted":              {-7, 10},
        "moreThanOneElement":               {1, 2, 3, 4},
        "moreThanOneElementWithRepetition": {1, 2, 4, 4},
        "moreThanOneElement2":              {-5, 0, 1, 7, 7, 10, 99},
        "sameElement":                      {1, 1, 1, 1},
        "negativeNumbers":                  {-10, -5, -3, -2, -1},
        "descendingOrder":                  {1, 2, 3, 4, 5},
        "randomOrder":                      {1, 2, 3, 4, 5, 6, 7, 8, 9},
        "duplicateElements":                {1, 1, 2, 2, 3, 3, 4, 4},
        "largeArray":                       {-1, -10000, -12345, -2032, -23, 0, 0, 0, 0, 10, 10000, 1024, 1024354, 155, 174, 1955, 2, 255, 3, 322, 4741, 96524},
        "singleNegativeElement":            {-7},
        "arrayWithZeroes":                  {-2, 0, 0, 0, 3},
        "ascendingOrder":                   {1, 2, 3, 4, 5},
        "descendingOrderWithDuplicates":    {1, 2, 3, 3, 4, 5, 5},
        "boundaryValues":                   {-2147483647, 2147483648},
        "mixedSignNumbers":                 {-2, -1, 0, 1, 2},
    },
}

func TestBubble(t *testing.T) {

    for testCase, array := range testData.ArrayList {
        t.Run(testCase, func(t *testing.T) {
            actual := Bubble(array)
            assert.ElementsMatch(t, actual, testData.ExpectedList[testCase])
        })

    }
}
Salin selepas log masuk
  • Kami pada asasnya mentakrifkan dua peta/senarai: satu untuk data input dan yang kedua untuk data yang dijangkakan. Kami memastikan bahawa setiap senario kes di kedua-dua belah pihak dirujuk melalui kunci peta yang sama di kedua-dua belah pihak.
  • Melaksanakan ujian kemudiannya adalah masalah gelung dalam fungsi mudah yang berulang ke atas senarai input/jangkaan yang disediakan.
  • Kecuali beberapa jenis plat dandang sekali sahaja, pengubahsuaian kepada ujian hanya sepatutnya berlaku pada bahagian data, kebanyakannya tiada perubahan harus mengubah logik fungsi melaksanakan ujian, sekali gus mencapai matlamat yang telah kita bincangkan di atas: mengurangkan kerja ujian hingga ke soal penyediaan data mentah.

Bonus: Repositori Github yang melaksanakan logik yang dibentangkan dalam catatan blog ini boleh didapati di sini https://github.com/MedUnes/dsa-go. Setakat ini ia mengandungi tindakan Github yang menjalankan ujian ini dan juga menunjukkan lencana hijau yang sangat terkenal itu ;)

Jumpa anda dalam siaran bermaklumat seterusnya [semoga]!

Atas ialah kandungan terperinci Daripada PHPUnit ke Go: Ujian Unit Terpacu Data untuk Pembangun Go. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:dev.to
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan