Menulis Ujian Unit dalam CFML dengan TestBox
Belajar menulis unit test CFML dengan TestBox. Panduan memasang melalui CommandBox, struktur describe, it dan expect, matchers dan ujian automatik dalam CI.

Kandungan
- Menulis Ujian Unit dalam CFML dengan TestBox
- Kenapa Ujian Penting
- Memasang TestBox melalui CommandBox
- Struktur Asas: describe, it dan expect
- Matchers dan Cakupan Pernyataan
- Gaya xUnit dengan assert
- Life-Cycle: beforeEach dan afterEach
- Mocking dengan MockBox
- Menjalankan Ujian dengan testbox run
- Menjalankan Ujian dalam CI
- Amalan Menulis Ujian yang Baik
- Matcher Lazim dalam TestBox
- Soalan Lazim (FAQ)
- Sumber
Menulis Ujian Unit dalam CFML dengan TestBox
TestBox ialah rangka kerja ujian untuk CFML dan BoxLang yang dibina di atas konsep BDD (Behavior Driven Development) dan TDD (Test Driven Development), menyediakan sintaks yang jelas untuk menulis ujian. Anda memasangnya melalui CommandBox sebagai kebergantungan pembangunan, menulis spec dengan describe, it dan expect, kemudian menjalankannya dari baris arahan atau dalam saluran CI. Artikel ini membimbing anda daripada pemasangan hingga amalan menulis ujian yang baik.
Kenapa Ujian Penting
Ujian automatik memberi anda jaring keselamatan apabila mengubah kod. Tanpa ujian, setiap perubahan pada komponen CFC membawa risiko memecahkan fungsi lain secara senyap, dan anda hanya mengetahuinya apabila pengguna melaporkan ralat. Dengan ujian, anda boleh refaktor dengan yakin kerana sebarang regresi dikesan serta-merta.
Dalam projek CFML yang bersifat monolitik, ujian juga bertindak sebagai dokumentasi hidup. Spec menerangkan bagaimana sesuatu komponen sepatutnya berkelakuan, dan ia sentiasa seiring dengan kod sebenar. Ini lebih dipercayai daripada komen yang mudah lapuk.
Memasang TestBox melalui CommandBox
TestBox dipasang sebagai kebergantungan pembangunan melalui CommandBox. Perhatikan bendera --saveDev yang menandakan TestBox sebagai kebergantungan pembangunan, bukan kebergantungan pengeluaran:
mkdir projek-saya --cd
box install testbox --saveDev
Penting untuk memahami bahawa TestBox tidak boleh digunakan dalam pengeluaran. Ia direka untuk persekitaran pembangunan dan ujian sahaja. Keperluan sistem TestBox menyokong Lucee 6.x dan Lucee 7.x, Adobe ColdFusion 2023 dan 2025, manakala sokongan untuk Adobe ColdFusion 2021 sudah digugurkan bermula TestBox 7.
Selepas memasang rangka kerja, pasang TestBox CLI untuk menjana dan menjalankan ujian dari CommandBox:
box install testbox-cli
testbox help
Arahan testbox generate harness akan menambah folder /tests ke dalam aplikasi anda bersama beberapa contoh ujian untuk memulakan anda. Folder itu mengandungi subfolder /specs untuk bundel ujian anda, dan fail runner.cfm untuk menjalankan ujian melalui pelayar.
Struktur Asas: describe, it dan expect
Satu suite ujian bermula dengan panggilan kepada fungsi describe(), yang menerima sekurang-kurangnya dua hujah: tajuk suite dan fungsi badan. Di dalam badan itu anda menulis spec individu menggunakan it(), dan di dalam setiap spec anda menyatakan jangkaan menggunakan expect():
component extends="testbox.system.BaseSpec" {
function run() {
describe( "Kalkulator saya", function() {
it( "boleh menambah dua nombor", function() {
var calc = new Kalkulator();
expect( calc.tambah( 1, 1 ) ).toBe( 2 );
} );
it( "boleh mendarab dua nombor", function() {
var calc = new Kalkulator();
expect( calc.darab( 2, 2 ) ).toBe( 4 );
} );
} );
}
}
Fungsi describe() juga mempunyai alias story(), feature(), scenario(), given() dan when(), supaya anda boleh memilih istilah yang paling sesuai dengan gaya BDD pasukan anda. Susunan ini menghasilkan output yang mudah dibaca: setiap spec yang lulus atau gagal dilaporkan dengan tajuknya.
Matchers dan Cakupan Pernyataan
Jangkaan dalam TestBox dimulakan oleh fungsi expect() yang mengambil nilai sebenar, kemudian dirantai dengan fungsi matcher yang membandingkan nilai itu dengan nilai dijangka. Setiap matcher juga mempunyai versi negatif dengan menambah awalan not:
describe( "Jangkaan TestBox", function() {
it( "membanding nilai dan jenis", function() {
expect( [1,2] ).toBe( [1,2] );
expect( "hello" ).toBeWithCase( "hello" );
expect( "hello" ).notToBeWithCase( "HELLO" );
expect( [] ).toBeEmpty();
expect( { nama="luis" } ).toHaveKey( "nama" );
} );
it( "mengesan pengecualian", function() {
expect( function() {
new Kalkulator().bahagi( 40, 0 );
} ).toThrow( regex="sifar" );
} );
} );
Antara matcher yang biasa digunakan ialah toBe untuk kesamaan, toBeTrue dan toBeFalse untuk boolean, toBeNull untuk nilai null, toBeInstanceOf untuk menyemak kelas, toMatch dan toMatchNoCase untuk ungkapan biasa, toBeTypeOf untuk menyemak jenis nilai, dan toHaveLength untuk saiz. Untuk koleksi, expectAll() mengambil tatasusunan atau struktur dan membolehkan anda menilai semua ahli sekaligus dengan toSatisfy().
Gaya xUnit dengan assert
Selain gaya BDD, TestBox turut menyokong gaya xUnit yang lebih tradisional. Anda menulis ujian dengan test() dan menggunakan pustaka assert seperti assertIsEqual:
function run() {
describe( "Kalkulator (gaya xUnit)", function() {
test( "boleh mendarab", function() {
var calc = new Kalkulator();
assertIsEqual( calc.darab( 2, 2 ), 4 );
} );
} );
}
Gaya xUnit sesuai untuk pasukan yang datang daripada rangka kerja ujian klasik, manakala gaya BDD dengan expect memberikan keterbacaan yang lebih tinggi. Kedua-duanya boleh hidup bersama dalam projek yang sama.
Life-Cycle: beforeEach dan afterEach
TestBox menyediakan kaedah life-cycle untuk menyediakan dan membersihkan keadaan ujian. beforeEach() dijalankan sebelum setiap spec dalam suite, dan afterEach() selepas setiap spec. Ini menghapuskan pertindihan kod penyediaan:
describe( "Kalkulator", function() {
beforeEach( function() {
variables.calc = new Kalkulator();
} );
it( "boleh menambah", function() {
expect( calc.tambah( 2, 3 ) ).toBe( 5 );
} );
it( "boleh menolak", function() {
expect( calc.tolak( 5, 3 ) ).toBe( 2 );
} );
} );
Dengan menyimpan objek dalam variables.calc, setiap spec mendapat contoh baharu tanpa perlu mengulang baris new Kalkulator(). Ini penting supaya ujian tidak berkongsi keadaan yang boleh mempengaruhi satu sama lain.
Mocking dengan MockBox
Untuk menguji komponen secara terasing, TestBox disertakan bersama MockBox, rangka kerja untuk mocking dan stubbing. Anda boleh mencipta objek palsu yang menggantikan kebergantungan sebenar, contohnya menggantikan panggilan pangkalan data dengan nilai tetap. Ini membolehkan anda menguji logik perniagaan tanpa memerlukan sambungan pangkalan data sebenar. Jika anda menguji komponen yang bergantung pada datasource, rujuk panduan konfigurasi datasource untuk memahami sambungan yang anda gantikan.
Menjalankan Ujian dengan testbox run
Setelah ujian ditulis, jalankan ia dari CommandBox. TestBox CLI membaca tetapan dari box.json atau menggunakan lalai /tests/runner.cfm:
testbox run
testbox run directory="tests.specs" outputFormats="json,junit,html"
testbox run runner="http://localhost:8080/tests/runner.cfm"
Anda boleh pratetap tetapan dalam box.json di bawah entri testbox, termasuk direktori, label, reporter dan format output. Terdapat juga watcher yang menjalankan ujian secara automatik apabila fail berubah:
testbox watch
Ini memberi gelung maklum balas yang pantas semasa pembangunan: anda mengubah kod, dan ujian berjalan dengan sendirinya.
Menjalankan Ujian dalam CI
TestBox boleh disepadukan dengan semua pelayan CI utama kerana anda hanya perlu melaksanakan suite ujian dan menghasilkan laporan. Pelayan CI seperti Jenkins, GitLab, Travis dan TeamCity semuanya disokong kerana output JUnit atau JSON boleh dibaca oleh alat ini.
Aliran kerja biasa dalam saluran CI ialah memulakan pelayan, menjalankan ujian, dan menyemak kod keluar:
server start
testbox run outputFormats="json,junit,html"
Laporan JUnit membolehkan pelayan CI memaparkan keputusan ujian secara berstruktur dan menandakan binaan sebagai gagal apabila ada ujian yang tidak lulus. Ini adalah lapisan kawalan kualiti yang menghalang kod rosak daripada sampai ke pengeluaran. Integrasi dengan Git dan aliran kerja cawangan diterangkan dalam panduan Git untuk projek CFML.
Amalan Menulis Ujian yang Baik
Ujian yang baik bersifat terasing, pantas dan boleh dipercayai. Setiap ujian sepatutnya menguji satu tingkah laku sahaja, supaya apabila ia gagal anda tahu dengan tepat apa yang rosak. Gunakan beforeEach untuk penyediaan dan elakkan kebergantungan antara ujian, kerana ujian yang bergantung pada urutan pelaksanaan akan menghasilkan kegagalan yang sukar dikesan.
Namakan spec dengan ayat yang menerangkan tingkah laku, bukan pelaksanaan. Contohnya "boleh menambah dua nombor" lebih baik daripada "menguji fungsi tambah". Apabila menguji komponen yang berinteraksi dengan pangkalan data, gunakan MockBox untuk menggantikan lapisan data supaya ujian berjalan pantas dan tidak bergantung pada data sebenar. Untuk komponen CFC yang anda uji, rujuk panduan fungsi dan komponen CFC sebagai asas.
Matcher Lazim dalam TestBox
expect() mengambil nilai sebenar dan dirantai dengan matcher untuk menyatakan jangkaan. Setiap matcher juga mempunyai versi negatif dengan awalan not.
| Matcher | Kegunaan | Contoh |
|---|---|---|
| toBe | Kesamaan nilai | expect(x).toBe(2) |
| toBeWithCase | Banding peka huruf | expect("hi").toBeWithCase("hi") |
| toBeEmpty | Semak nilai kosong | expect([]).toBeEmpty() |
| toHaveKey | Semak kunci wujud | expect(s).toHaveKey("nama") |
| toThrow | Kesan pengecualian | expect(fn).toThrow(regex="sifar") |
Pilih matcher yang paling jelas menggambarkan jangkaan anda supaya kegagalan mudah difahami.
Soalan Lazim (FAQ)
Apakah TestBox dalam CFML?
TestBox ialah rangka kerja ujian berasaskan BDD dan TDD untuk CFML dan BoxLang daripada Ortus Solutions. Ia menyediakan sintaks describe, it dan expect untuk menulis ujian, serta sokongan xUnit, matchers, MockBox dan laporan untuk CI.
Bagaimana cara memasang TestBox?
Guna CommandBox dan jalankan box install testbox --saveDev untuk memasangnya sebagai kebergantungan pembangunan. Kemudian pasang TestBox CLI dengan box install testbox-cli untuk menjana dan menjalankan ujian.
Apakah perbezaan antara describe dan it?
describe() mentakrifkan suite ujian dan menerima tajuk serta fungsi badan, manakala it() mentakrifkan satu spec individu di dalam suite itu. expect() digunakan di dalam spec untuk menyatakan jangkaan.
Bagaimana cara menjalankan ujian TestBox?
Jalankan testbox run dari CommandBox selepas memulakan pelayan. Anda boleh menentukan direktori, format output dan URL runner melalui hujah atau tetapan box.json.
Bolehkah TestBox digunakan dalam pengeluaran?
Tidak. TestBox direka untuk pembangunan dan ujian sahaja. Dokumentasi rasmi dengan jelas menyatakan agar tidak menggunakan TestBox dalam persekitaran pengeluaran.