Perkakas crystal

Menggunakan perintah crystal run, build, spec, dan init pada proyek pertama.

Daftar isi

Perkakas baris perintah crystal menyatukan pekerjaan sehari-hari dalam satu program: crystal run untuk mencoba kode, crystal build untuk menghasilkan binary, crystal init untuk membuat kerangka proyek, dan crystal spec untuk menjalankan pengujian. Topik ini menggunakan keempatnya secara berurutan pada proyek pertama bernama penghitung-kata, dimulai dari satu berkas sederhana sampai proyek dengan spec yang hijau. Pola kerjanya sama untuk proyek apa pun, sehingga kebiasaan yang terbentuk pada topik ini langsung terpakai pada proyek yang sesungguhnya.

Menjalankan berkas dengan crystal run#

Perintah crystal run mengompilasi berkas .cr lalu langsung mengeksekusinya dalam satu langkah. Perintah ini paling cepat digunakan ketika kode masih berupa satu berkas dan hasilnya cukup diamati dari terminal. Compiler menyimpan hasil kompilasi pada cache, sehingga menjalankan ulang berkas yang belum berubah biasanya lebih cepat daripada eksekusi pertamanya.

crystal jumlah.cr
def jumlah(a : Int32, b : Int32) : Int32
  a + b
end

puts jumlah(2, 3)
bash
# jalankan berkas tunggal lewat compiler
crystal run jumlah.cr
text Keluaran
5

Berkas jumlah.cr mendefinisikan metode jumlah dengan anotasi tipe pada parameter dan nilai baliknya, kemudian mencetak hasil pemanggilan dengan puts. Keluaran 5 adalah hasil penjumlahan kedua argumen tersebut. Perintah run tidak meninggalkan berkas baru di direktori kerja, sehingga berkas sumber tetap satu-satunya yang perlu dikelola pada tahap ini.

Secara internal, crystal run menempatkan binary sementara di luar direktori kerja, menjalankannya, lalu membuangnya. Pola kerja yang lazim adalah menyunting kode, menjalankan crystal run lagi, dan membaca keluarannya, berulang sampai perilaku yang diinginkan tercapai. Kecepatan tahap kompilasi yang memanfaatkan cache membuat siklus ini tetap ringan untuk berkas kecil.

Membangun binary dengan crystal build#

Perintah crystal build mengompilasi berkas menjadi binary tanpa menjalankannya. Opsi -o menentukan nama binary yang dihasilkan, dan binary tersebut dapat dijalankan langsung maupun disalin ke mesin lain dengan arsitektur yang sama tanpa perlu compiler terpasang. Perintah yang berhasil tidak mencetak apa pun, sehingga tidak adanya keluaran justru menandakan build selesai tanpa masalah.

bash
# build menjadi binary bernama jumlah
crystal build -o jumlah jumlah.cr

# jalankan binary hasil build
./jumlah
text Keluaran
5

Binary jumlah kini berdiri sendiri. Eksekusinya tidak lagi melalui compiler, sehingga waktunya lebih singkat dan berkasnya dapat didistribusikan seperti program lain pada umumnya.

Ukuran binary hasil build jauh lebih besar daripada kode sumbernya karena menyertakan runtime dan pustaka standar yang digunakan program. Konsekuensinya wajar: binary memang dirancang untuk didistribusikan, sedangkan kode sumber tetap menjadi berkas utama yang disunting. Selama tahap pengembangan, crystal run menggantikan langkah build ini karena keduanya menggunakan jalur kompilasi yang sama.

Membuat kerangka proyek dengan crystal init#

Proyek yang lebih dari satu berkas membutuhkan struktur yang konsisten, dan perintah crystal init app membuatnya sekaligus. Perintah berikut membuat kerangka aplikasi bernama penghitung-kata pada folder baru. Nama proyek menentukan nama foldernya, nama module di dalam kode, dan nama berkas sumber utamanya.

bash
# buat kerangka proyek aplikasi penghitung-kata
crystal init app penghitung-kata
text Keluaran
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/.gitignore
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/.editorconfig
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/LICENSE
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/README.md
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/shard.yml
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/src/penghitung-kata.cr
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/spec/spec_helper.cr
    create  /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/spec/penghitung-kata_spec.cr
Initialized empty Git repository in /home/kal/my-project/content/crystal/mengenal-crystal/perkakas-crystal/penghitung-kata/.git/

Baris create mencantumkan setiap berkas yang dibuat, sedangkan baris terakhir berasal dari git yang menginisialisasi repositori di dalam folder proyek. Jalur absolut pada keluaran mengikuti tempat perintah dijalankan, sehingga isinya pasti berbeda pada mesin yang lain. Struktur yang terbentuk adalah sebagai berikut.

text Struktur proyek penghitung-kata
penghitung-kata/
├── .editorconfig
├── .gitignore
├── LICENSE
├── README.md
├── shard.yml
├── spec/
│   ├── penghitung-kata_spec.cr
│   └── spec_helper.cr
└── src/
    └── penghitung-kata.cr

Berkas shard.yml menjadi manifest proyek yang memuat nama, versi, penulis, target build, batas versi Crystal, dan lisensi. Folder src/ menampung kode sumber, sedangkan spec/ menampung pengujian dengan spec_helper.cr sebagai penyiapan yang dimuat setiap kali spec dijalankan. Nama Penghitung::Kata pada kode bawaan diambil dari nama proyek, dengan tanda hubung diubah menjadi pemisah namespace ::.

Berkas README.md masih berupa templat penjelasan proyek, LICENSE memuat lisensi MIT sesuai manifest, sedangkan .editorconfig menyimpan kesepakatan indentasi agar berkas yang ditulis dari editor berbeda tetap seragam. Folder .git/ yang terbentuk paling akhir tidak perlu disunting karena isinya dikelola git. Seluruh berkas ini boleh disesuaikan setelah proyek berjalan, misalnya melengkapi README atau mengganti lisensinya.

crystal Isi bawaan src/penghitung-kata.cr
# TODO: Write documentation for `Penghitung::Kata`
module Penghitung::Kata
  VERSION = "0.1.0"

  # TODO: Put your code here
end
crystal Isi bawaan spec/penghitung-kata_spec.cr
require "./spec_helper"

describe Penghitung::Kata do
  # TODO: Write tests

  it "works" do
    false.should eq(true)
  end
end

Kode sumber bawaan hanya mendefinisikan module Penghitung::Kata dengan konstanta VERSION, sedangkan spec bawaan memuat satu contoh pengujian yang isinya masih asersi pengganti. Kata TODO pada baris komentar menandai pekerjaan yang belum selesai dan tidak memengaruhi perilaku program. Kedua berkas inilah yang diperbarui pada bagian berikutnya.

Menjalankan pengujian dengan crystal spec#

Crystal menyertakan framework spec, kerangka pengujian bawaan yang mengorganisir pengujian dengan describe dan it. Perintah crystal spec mengompilasi folder spec/ beserta kode sumber yang dirujuk, lalu menjalankan seluruh contohnya. Spec bawaan hasil init sengaja dibuat gagal oleh generator proyek.

bash
# masuk ke folder proyek
cd penghitung-kata

# jalankan spec bawaan
# baris "Finished in" disaring karena waktunya selalu berubah
crystal spec 2>&1 | grep -v "^Finished in"
text Keluaran
F

Failures:

  1) Penghitung::Kata works
     Failure/Error: false.should eq(true)

       Expected: true
            got: false

     # spec/penghitung-kata_spec.cr:7

1 examples, 1 failures, 0 errors, 0 pending

Failed examples:

crystal spec spec/penghitung-kata_spec.cr:6 # Penghitung::Kata works

Huruf F pada baris pertama menandai satu contoh gagal, dan bagian Failures memerinci kegagalannya. Baris Expected dan got memperlihatkan nilai yang diharapkan berbanding nilai aktual dari asersi eq(true). Baris komentar # spec/penghitung-kata_spec.cr:7 menunjuk lokasi asersi yang gagal, sedangkan ringkasan menyebut satu contoh dieksekusi dengan satu kegagalan. Bagian Failed examples mencetak perintah siap pakai untuk menjalankan ulang contoh yang gagal secara terisolasi.

spec_helper.cr yang dimuat di baris pertama spec memuat pustaka spec sekaligus kode sumber proyek melalui require "../src/penghitung-kata". Berkas ini menjadi tempat pertama yang disentuh ketika proyek kelak membutuhkan penyiapan bersama, misalnya membangun objek contoh yang digunakan beberapa spec. Untuk saat ini, isi bawaannya sudah cukup.

Perbaikan dilakukan dengan mengganti isi kedua berkas bawaan secara utuh. src/penghitung-kata.cr diisi metode jumlah pada module Penghitung::Kata, dan spec bawaan diganti asersi yang memeriksa hasil penjumlahannya. Isi yang lama tidak dipertahankan karena kedua TODO sudah tidak diperlukan.

crystal src/penghitung-kata.cr
module Penghitung::Kata
  VERSION = "0.1.0"

  def self.jumlah(a : Int32, b : Int32) : Int32
    a + b
  end
end
crystal spec/penghitung-kata_spec.cr
require "./spec_helper"

describe Penghitung::Kata do
  it "menjumlahkan dua bilangan" do
    Penghitung::Kata.jumlah(2, 3).should eq(5)
  end
end

Pada tutorial ini kedua versi final tersimpan sebagai berkas contoh di samping folder proyek, sehingga perintah berikut menyalinnya ke tempat semestinya. Perintah cp dijalankan dari dalam folder proyek, sehingga jalur ../ menunjuk folder tempat berkas contoh berada. Saat mengerjakan proyek sendiri, isi kedua berkas tersebut juga dapat ditulis ulang secara manual sesuai potongan di atas.

bash
# salin berkas contoh di samping proyek ke tempat semestinya
cp ../src/penghitung-kata.cr src/penghitung-kata.cr
cp ../spec/penghitung-kata_spec.cr spec/penghitung-kata_spec.cr

# jalankan ulang spec dengan saringan yang sama
crystal spec 2>&1 | grep -v "^Finished in"
text Keluaran
.

1 examples, 0 failures, 0 errors, 0 pending

Titik pada baris pertama berarti satu contoh lolos, dan ringkasan mengonfirmasi nol kegagalan. Ringkasan seperti ini selalu menutup setiap eksekusi spec, sehingga perubahan kegagalan mudah terbaca dari satu barisnya. Metode jumlah kini diuji oleh spec yang berjalan setiap kali crystal spec dipanggil, sehingga menjadi titik kontrol pertama proyek ini.

Ringkasan#

  • crystal run mengompilasi dan mengeksekusi berkas .cr dalam satu langkah, cocok untuk percobaan cepat.
  • crystal build menghasilkan binary mandiri melalui opsi -o yang dapat dijalankan tanpa compiler.
  • crystal init app membuat kerangka proyek berisi shard.yml, folder src/ dan spec/, serta repositori git.
  • crystal spec menjalankan pengujian, dan spec bawaan sengaja gagal sampai asersi pertama ditulis.

Referensi#