Bagaimana Anda menguji suatu fungsi yang tujuan utamanya adalah untuk query API eksternal, tetapi API menggunakan sintaks query yang kompleks?

16

Satu-satunya logika nyata adalah dalam sintaks kueri untuk API eksternal. Saya tidak ingin menguji apakah ia meminta api, saya ingin menguji apakah ia menanyakannya sedemikian rupa sehingga data yang benar akan dikembalikan. Sebagai contoh, beberapa kode semu:

function retrieve_related_data(id)
{
  query = "[potentially long, syntactically complex query that
            uses param id to get some data]";
  results = api_wrapper.query(query);
  return results;
}

Contoh yang lebih konkret dengan API buatan:

function retrieveLifeSupportingObjectsWithinRegion(id)
{
  query = "
    within region(" + id + ") as r
    find objects matching hydration>0 and temp_range has 75
    send name, id, relative(position, r)        
  ";
  results = astronomicalObjectApiWrapper.query(query);
  return results;
}

Kueri dalam kustom sintaksis untuk API dan kompleks dan ada beberapa cara untuk mencapai hasil yang sama atau mirip. Tujuan dari fungsi ini bukan untuk mendapatkan data yang diidentifikasi oleh idtetapi untuk menemukan subset dari data lain berdasarkan pada hubungan fuzzy dengan data yang diidentifikasi oleh idyang juga memenuhi beberapa persyaratan lainnya. Persyaratan lain selalu sama terlepas dari idtetapi dapat berubah seiring waktu ketika sistem dimodifikasi. Misalnya, jika contoh api menambahkan dukungan untuk informasi gayaberat, kami mungkin ingin mengubah kueri untuk juga menggunakan gayaberat untuk menyaring hasilnya. Atau mungkin kita menemukan cara yang lebih efisien untuk memeriksa rentang temp, tetapi itu tidak mengubah hasilnya.

Yang ingin saya uji adalah bahwa untuk input yang diberikan idset data yang benar dikembalikan. Saya ingin menguji ini sehingga jika seseorang mengacaukan kueri sehingga tidak lagi mengembalikan data yang benar berdasarkan iditu akan gagal, tapi saya juga ingin orang dapat memodifikasi kueri untuk memperbaikinya tanpa perlu juga memodifikasi ujian.

Opsi yang saya pertimbangkan:

  1. Saya bisa mematikan api, tetapi itu bisa terlalu sederhana (periksa idapakah ada dalam kueri dan kemudian mengembalikan set data yang diharapkan jika itu atau set yang tidak terduga jika tidak), terlalu rapuh (periksa apakah string kueri persis apa yang ada dalam fungsi), atau terlalu rumit (periksa apakah permintaan yang digunakan benar secara sintaksis dan akan menghasilkan data yang benar dikembalikan).

  2. Saya dapat mengirimkan kueri ke api nyata, tetapi hasil yang diharapkan dapat berubah seiring waktu karena data dalam sistem eksternal berubah, di luar kendali sistem pengujian.

  3. Saya bisa melihat menyiapkan uji coba api nyata untuk mengontrol data yang dimilikinya, tapi itu banyak usaha.

Saya condong ke arah # 2 dan menjadikan ini lebih sebagai tes integrasi yang tidak sering dijalankan dan melihat seberapa sering perubahan dalam data sistem eksternal menyebabkan tes rusak. Saya pikir itu akan menjadi paling sederhana untuk saat ini, tetapi saya bertanya-tanya apakah ada alternatif yang tidak saya pikirkan atau cara yang lebih baik untuk mengatasi masalah ini. Nasihat apa pun akan dihargai.

Joshua Coady
sumber
Saya menganggap ini sebagai tes unit, tapi mungkin itu benar-benar tes integrasi atau tes penerimaan tingkat rendah?
Joshua Coady
2
Apakah itu API hanya baca? Atau, apakah Anda dapat menulis data yang dapat Anda andalkan memverifikasi bacaan Anda ?
svidgen
Apakah pertanyaan ini berbeda dari "bagaimana cara menguji sql saya (= sintaksis kompleks) mengembalikan data yang benar"? Dengan database, Anda biasanya memiliki beberapa tes integrasi yang menguji sintaks crud-sql dan repositori tiruan untuk memverifikasi businesslogic
k3b

Jawaban:

7

Tampaknya memvalidasi respons API eksternal kami akan menguji fungsi kami, tetapi itu tidak sepenuhnya benar. Entah bagaimana, kami akan menguji API eksternal dan lingkungan tempat API berjalan.

Tes kami harus ditujukan untuk menjamin perilaku yang diharapkan dari kode yang kami tulis, bukan yang ditulis oleh pihak ke-3.

Untuk tingkat tertentu, kita harus percaya pada fungsi API dan lib yang tepat yang kita andalkan. Misalnya, kami biasanya tidak menguji komponen kerangka yang kami laksanakan.

Kenapa saya bilang begitu?

Yang ingin saya uji adalah bahwa untuk id input yang diberikan set data yang benar dikembalikan

Apa yang akan diuji di sini? Seperti yang Anda katakan, data dan kebenarannya tidak di bawah kendali kami, jadi kami akan membatasi keberhasilan fase pengujian ke agen eksternal yang kami tidak memiliki kendali. Tes ini adalah kandidat untuk menjadi non-deterministik dan pasti, kami tidak ingin tes semacam ini dalam pipa bangunan kami .

Masalah lain adalah memvalidasi kontrak. Saya akan menemukan bahwa kontrak 1 sangat berguna untuk memastikan bahwa integrasi masih berfungsi seperti yang diharapkan, sebelum rilis atau penyebaran.

Saya ingin menguji ini sehingga jika seseorang mengacaukan kueri sehingga tidak lagi mengembalikan data yang benar berdasarkan id bahwa itu akan gagal

Bagaimana jika kueri itu ok, tetapi datanya salah karena bug di API? Tidak hanya data di luar kendali kami. Logikanya juga.

Menerapkan tes fungsional atau tes ujung ke ujung dapat membantu di sini. Anda bisa mengatasi tes ini untuk memvalidasi jalur eksekusi tertentu sehingga jika API mengembalikan data yang salah, ini mungkin akan menyebabkan perilaku dan hasil yang tidak terduga. Di sisi lain, saya akan mengharapkan API untuk melakukan kesalahan jika pertanyaan saya tidak diformat dengan baik.

Tapi saya juga ingin orang dapat memodifikasi kueri untuk memperbaikinya tanpa perlu juga memodifikasi tes.

Saya sarankan menerapkan alat untuk tujuan tersebut. Ini bisa sesederhana:

  • Kelas yang dijalankan sebagai tes tetapi bukan milik rencana tes
  • Script shell + curl

Atau sesuatu yang lebih canggih. Misalnya, klien mandiri.

Bagaimanapun, fungsi di bawah pertanyaan, layak dua jenis tes:

  • Tes Unit. Seperti yang Anda katakan, Anda harus mematikan API eksternal, tetapi itulah tujuan keseluruhan dari tes unit. Menguji kode kami mengisolasi dependensi.

  • Tes integrasi. Pastikan kode tidak hanya mengirimkan permintaan yang benar tetapi juga menangani konten respons, kesalahan, pengalihan, dan lain-lain dengan benar. Lakukan tes untuk semua kasus ini, tetapi jangan menguji data .

Catatan: Pertanyaan Anda mirip dengan - bagaimana Anda menguji pernyataan SQL aplikasi-?

Pertanyaan terkait :


1: Anda mungkin tertarik pada jawaban @ DocBrown mengenai topik ini

Laiv
sumber
"Masalahnya (IMO) adalah Anda terlalu fokus menguji API eksternal." - Saya tidak melihat apa pun yang menunjukkan bahwa penanya tertarik untuk menguji API eksternal sama sekali. Juga, Anda mengatakan "rintisan API eksternal", tetapi apakah Anda memiliki saran apakah penanya harus menggunakan opsi "terlalu sederhana", opsi "terlalu rapuh", opsi "terlalu rumit", atau beberapa opsi keempat?
Tanner Swett
Pertanyaan OP menanyakan bagaimana menguji suatu fungsi yang memanggil ke API eksternal. Tetapi membaca keraguannya, bagi saya sepertinya dia terlalu menekankan pengujian kueri dan hasilnya. Saya membuat 4 saran: (1) jangan lakukan uji API. (2) jangan gunakan tes integrasi sebagai meja kerja untuk menyetel kueri. Buatlah alat sebagai gantinya. (3) kembali ke pertanyaan utama, lakukan uji kesatuan dan Integrasi. Tetapi tidak memvalidasi konten dari respons API. (4) Tanyakan kepada manajer proyek apakah mereka harus / dapat membuat paket uji API eksternal sebagai bagian dari rencana pengujian proyek.
Laiv
1
Saya menganggap permintaan itu sendiri sebagai "kode yang kami tulis". Tujuan akhir adalah pengujian otomatis untuk memberi tahu kami jika kami memperkenalkan bug dalam kode kami. Membawa apa yang Anda katakan tentang pernyataan SQL, saya kira itu mirip dengan itu - saya kira pertanyaan saya adalah seperti bagaimana Anda menguji bahwa kode Anda menanyakan API eksternal dengan cara yang akan direspon oleh API sebagaimana dimaksud (dengan asumsi respon nominal). Saya pikir apa yang Anda katakan adalah untuk meninggalkan yang keluar dari unit dan tes integrasi, tetapi jika pertanyaan sangat penting, kami dapat mengatur beberapa tes otomatis lainnya secara terpisah untuk menguji api eksternal langsung.
Joshua Coady
1
IMO, cara terbaik adalah melakukan tes fungsional, perubahan di mana klausa yang tidak akan pernah benar, akan menyebabkan behaivor berbeda dalam satu atau lebih tes fungsional saya. UT hanya sebagian kecil dalam rencana pengujian.
Laiv
2
Terima kasih telah menjadi papan suara. Saya kira pada akhirnya, meskipun kueri memiliki logika khusus di dalamnya, itu di luar domain pengujian unit karena permintaan adalah kode yang "dieksekusi" di luar sistem yang sedang diuji. Saya hanya perlu seseorang untuk memberi tahu saya bahwa beberapa kali dengan cara yang berbeda sebelum saya melihatnya;)
Joshua Coady
2

Saya telah melihat pemeriksaan unit yang memeriksa string kueri yang dihasilkan cocok dengan nilai yang diharapkan.

Namun. Ini menurut saya jika penggunaannya terbatas. Sintaks kueri rumit, mungkin buggy, jadi A ada kemungkinan tak terbatas untuk memeriksa dan B bahkan jika string itu 'benar' dihasilkan, hasil yang tidak terduga dapat dikembalikan di lingkungan langsung.

Saya pikir Anda benar untuk pergi untuk pilihan Anda 2. menjalankan tes integrasi terhadap contoh langsung.

Selama mereka tidak merusak, ini adalah tes pertama yang harus Anda tulis, karena mereka akan menangkap, meskipun tidak mengidentifikasi penyebab, kesalahan apa pun.

Pergi untuk opsi 3 'menyebarkan contoh uji dengan data dummy' lebih unggul. Tetapi tidak memengaruhi penulisan tes Anda, karena Anda dapat mengarahkan tes yang sama di server pengujian jika dan saat penggunaan waktu yang baik untuk menggunakannya.

Ewan
sumber
0

Tergantung pada API, tetapi jika mungkin, pilih opsi # 3 (contoh pengujian pribadi).

Menonaktifkan API (opsi # 1) adalah opsi terburuk, karena alasan yang Anda sebutkan, dan pergi dengan rute ini mungkin akan lebih berbahaya daripada baik (banyak waktu terbuang).

Berlari melawan API nyata (opsi # 2) membuat pengujian tidak stabil dan tidak dapat diandalkan, dan setelah beberapa kesalahan positif orang akan berhenti menggunakannya. Tidak hanya data dapat berubah, tetapi layanan mungkin turun juga. Menurut pendapat saya, ini mirip dengan tidak memiliki tes untuk pertanyaan, dan mengandalkan tes integrasi / sistem untuk menemukan masalah. Yang mengatakan, jika data API jarang berubah dan API itu sendiri hampir selalu naik, maka ini mungkin menjadi opsi yang layak. Sebagian besar API tidak sesuai dengan deskripsi ini.

Akhirnya turun ke seberapa penting dan kompleks pertanyaan ini adalah: jika ada lebih dari segelintir, dan beberapa dari mereka cukup kompleks sehingga Anda merasa perlu untuk mengujinya, saya akan menginvestasikan upaya mendirikan contoh pribadi untuk pengujian . Ini akan membayar sendiri seperti halnya unit test lainnya.

Michal Tenenberg
sumber
Jadi pada dasarnya, Anda mengatakan bahwa tes unit (# 1) dan tes integrasi (# 2) berbahaya? Sementara # 3 mungkin tampak yang terbaik di antara mereka, itu bisa juga yang paling mahal. Itu harus dipertahankan setiap kali perubahan API. Tanpa # 2 Anda tidak akan menyadari kemungkinan perubahan bug di API asli hingga aplikasi Anda diproduksi (terlambat untuk mengambil tindakan). Oke, # 1 tampaknya tidak dibutuhkan karena tidak ada baris kode untuk diuji ... hari ini ... Besok, bagaimana tahu ...
Laiv
Saya mengatakan tes buruk berbahaya, tentu saja. Tes serpihan menghabiskan banyak waktu dan usaha, dan menyebabkan orang kehilangan kepercayaan pada unit test secara keseluruhan. Tes yang terputus dengan perubahan implementasi (# 1) atau hanya secara acak ketika data berubah (# 2) bukan tes yang baik.
Michal Tenenberg
Tes integrasi tidak menguji data. Itu dia. Mereka tidak dapat memecahkan pengujian, hanya memvalidasi integrasi. Menguji bukanlah masalah iman adalah masalah memiliki kebiasaan baik yang menambah nilai pada aplikasi
Laiv