Menguji klien REST terhadap Server REST. Bagaimana melakukan jadwal?


10

Saat menulis tes unit, biasanya menggunakan perlengkapan: sedikit data yang dapat diuji, sehingga kita dapat mengatakan: 1. Dapatkan semua klien harus menyertakan Willy Wonka. 2. Hapus klien 3, dan sekarang dapatkan klien tidak harus menyertakan Willy Wonka lagi.

Itu bagus untuk tes unit. Gunakan pengaturan / teardown untuk memuat kembali perlengkapan atau mengembalikan transaksi. Jadi pengujian menciptakan, memperbarui, dan menghapus dilakukan di dalam suatu transaksi . Data sementara yang baru berlangsung hanya selama lamanya tes itu, kemudian diatur ulang.

Tapi bagaimana kalau kita memisahkan server REST dari klien REST?

Kami ingin memastikan klien REST kami tidak hanya membaca dengan benar, tetapi membuat, memperbarui, dan menghapus dengan benar.

Saya belum dapat menemukan contoh atau saran untuk cara melakukan ini terhadap server REST uji jarak jauh.

Dengan asumsi saya punya server uji REST hanya melayani perlengkapan. Seluruh sifat HTTP tanpa kewarganegaraan berarti akan sulit untuk mengirim jenis "TRANSAKSI BEGIN" dan "TRANSAKSI ROLLBACK" atau "RELOAD FIXTURES", kan?

Saya tidak bisa menjadi yang pertama ingin melakukan ini, jadi saya merasa saya perlu cara berpikir yang berbeda tentang ini.

Ada saran?


Mungkin, karena ini adalah server uji, Anda dapat memiliki titik akhir yang akan memuat ulang perlengkapan?
David Radcliffe

Jika masalah utama Anda adalah membawa server pengujian Anda kembali ke keadaan yang telah ditentukan, mengapa Anda tidak menambahkan beberapa jenis fungsi pengujian khusus seperti "RELOAD TESTDATA" ke API sisanya untuk melakukan apa yang Anda inginkan? Tentu saja, Anda harus memastikan jenis panggilan API tidak tersedia dalam produksi.
Doc Brown

Jawaban:


7

Sistem perangkat lunak idealnya memiliki batasan sistem yang jelas dan antarmuka di antara mereka. Layanan REST adalah contoh yang bagus untuk ini.

Untuk itu, saya akan merekomendasikan untuk tidak melakukan apa yang Anda coba lakukan.

Secara khusus:

Kami ingin memastikan klien REST kami tidak hanya membaca dengan benar, tetapi membuat, memperbarui, dan menghapus dengan benar.

Apa yang saya sarankan adalah:

  • Membangun tes untuk klien REST Anda, untuk memastikannya berperilaku dengan benar, diberikan input dan output spesifik. Akun untuk nilai baik (diharapkan) dan buruk (tidak terduga).

  • Membangun tes untuk layanan REST Anda (jika Anda mengendalikannya, yaitu), untuk berperilaku sesuai dengan fungsi yang dimaksudkan

  • Simpan tes dekat dengan domain masalahnya, sehingga dapat membantu memandu desain dan pengembangan apa yang penting dalam konteks itu


3
Anda mengabaikan seluruh gagasan tes integrasi di sini dengan santai. Saya tidak berpikir pendekatan ini diinformasikan dari latihan.
febeling

Terima kasih atas semua saran yang bermanfaat. Juga oleh Twitter saya mendapat saran bagus untuk mencoba Ruby gem "webmock" dan mirip dengan mengejek respons server REST API. Saya juga setuju dengan "febeling" bahwa apa yang saya uraikan tampaknya lebih merupakan tes integrasi, jadi saya akan memeriksanya secara terpisah. Terima kasih sekali lagi semuanya. - Derek
sivers

mengejek API adalah cara terbaik untuk menyelesaikan masalah. Tetapi bagaimana Anda memastikan bahwa API yang dipermainkan == API asli?
FrEaKmAn

4

Dua sudut yang perlu diingat di sini:

  • Apakah Anda menguji kode Anda atau pipa ledeng? Menganggap Anda menggunakan layanan dan tumpukan klien yang Anda ketahui mungkin dapat dengan aman mengandaikan penguji mereka dan ribuan pengguna pada umumnya akan memastikan tidak ada bug mendasar pada dasarnya.
  • Mengapa tes Anda tidak idempoten? Buat cara untuk menulis data non-produksi atau menulis ke titik akhir yang berbeda. Pilih beberapa pola penamaan yang dapat diprediksi. Pra-memuatkan server DB sisanya sebelum pengujian. Dan mungkin ada beberapa cara untuk mewujudkan hal ini - metode ini sangat taktis dan harus bergantung pada sifat aplikasi.


1

Seperti yang dikatakan orang lain, jika Anda menguji klien, Anda tidak perlu membuat, menghapus, dll. Di server. Sering kali Anda bahkan tidak perlu mengejek server sama sekali. Anda benar-benar hanya perlu memastikan bahwa Anda membuat permintaan yang tepat dan menangani respons dengan benar, Baik itu ditulis dalam Ruby, Python, PHP atau apa pun, pada titik tertentu klien Anda mungkin akan menggunakan metode dari perpustakaan HTTP untuk membuat permintaan dan itu cukup untuk mengejek metode itu, memeriksa bagaimana namanya, dan mengembalikan hasil tes.

Ambil klien Python hipotetis yang digunakan urllib2untuk membuat permintaan. Anda mungkin memiliki beberapa metode di klien, sebut saja get(), yang memiliki panggilan untuk urllib2.Request()itu. Anda hanya perlu mengejek panggilan ke kelas Anda sendiri get().

@patch('your.Client.get')
def test_with_mock(self, your_mock):
    your_mock.return_value({'some': 'json'})
    test_obj = your.Client.get_object(5)
    your_mock.assert_called_with('/the/correct/endpoint/5')

Contoh yang sangat sederhana ini menggunakan Python Mock library untuk menguji your.Clientkelas hipotetis dengan get_object()metode yang menghasilkan url yang benar untuk mendapatkan sesuatu dari beberapa API. Untuk mengajukan permintaan, klien memanggil get()metode dengan url itu. Di sini, metode itu diejek ( your.Client.get"ditambal" sehingga berada di bawah kendali your_mock), dan tes memeriksa apakah titik akhir yang tepat diminta.

Metode mengejek mengembalikan respons JSON yang dikonfigurasi ( your_mock.return_value) yang harus ditangani oleh klien dan Anda akan membuat pernyataan lebih lanjut untuk menguji apakah ia menangani data yang diharapkan dengan cara yang diharapkan.


Tetapi bagaimana Anda yakin bahwa ketika Anda membuat permintaan "benar" bahwa itu adalah permintaan (dalam produksi) yang sebenarnya? Karena jika saya memahami saran Anda, jika API berubah atau rusak, pengujian Anda akan tetap berfungsi. Sementara dalam produksi itu cerita yang sama sekali berbeda.
FrEaKmAn

1

Apa yang Anda gambarkan adalah skenario uji integrasi. Ini biasanya agak canggung untuk pengaturan dan meruntuhkan. Itu membuat mereka lambat untuk berjalan dan cukup sering rapuh.

Pendekatan dengan fixture sama canggung dan kikuk, tetapi itu adalah cara standar beberapa kerangka kerja tentang hal itu, misalnya Rails, dan sudah didukung. Mereka membutuhkan test case abstrak atau yang serupa untuk mempersiapkan database dengan fixture. (Waspadalah terhadap penamaan kategori tes yang tidak biasa di Rails, tes unit dengan DB fixture juga merupakan tes integrasi.)

Cara saya akan melakukan skenario Anda adalah untuk menerima memiliki kontrol khusus tes atas keadaan aplikasi API atau database-nya. Anda dapat memiliki titik akhir tambahan untuk pengaturan dan teardown, yang hanya ada di lingkungan pengujian. Atau sebagai alternatif, Anda berbicara dengan basis data (atau apa pun yang Anda gunakan) di belakang aplikasi / API Anda.

Jika Anda merasa ini terlalu banyak (dalam arti tidak semestinya) upaya, maka pertimbangkan bahwa pendekatan dengan perlengkapan untuk database tidak hanya itu: menggunakan sarana tambahan, uji khusus untuk memanipulasi basis data atau keadaan aplikasi.

Saya tidak berpikir diskusi ini ada hubungannya dengan sifat HTTP tanpa kewarganegaraan. HTTP bersifat stateless, tetapi aplikasinya jelas tidak, dalam sebagian besar kasus. Kedengarannya agak seperti Anda di mana mencari keketatan REST. Anda bisa saja membuat semua sumber daya sepenuhnya dapat diciptakan, dibaca dan dihapus. Dalam hal ini Anda bisa melakukan semua pengaturan dan teardown melalui cara API biasa. Ini sering tidak dilakukan dalam praktik, karena Anda tidak ingin memasukkan operasi tertentu dari pemahaman bisnis aplikasi Anda, setidaknya tidak di luar lingkungan pengujian.


1

Patch monyet

Di tempat kerja saya, kami melakukan ATDD dengan menggunakan kerangka xUnit yang keluar dan pemanggilan jaringan monyet antara klien dan server. Dalam ruang proses yang sama kami memuat klien, monyet menambal panggilan jaringan ke bagian atas kode tumpukan server REST. Semua panggilan kemudian dikeluarkan dari klien seperti biasanya, dan kode server mendapatkan permintaan persis seperti biasanya.

Manfaat

  • tidak perlu melakukan sinkronisasi dengan startup server (karena tidak ada server)
  • memanfaatkan pengaturan unit klasik dan metode teardown untuk mengelola hal-hal seperti perlengkapan
  • kemampuan untuk menggunakan tiruan / bertopik dan tambalan monyet lainnya untuk kontrol tes lebih berbutir
  • dapat ditulis menggunakan bingkai xUnit

Pengorbanan

  • tidak memaparkan interaksi / masalah multi-proses (penguncian, kelaparan sumber daya, dll)
  • tidak memunculkan masalah multi-server (serialisasi data, gaya clustering)
  • tidak memaparkan masalah jaringan karena itu disimulasikan (akses, kesalahan batas waktu, dll)
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.