Pengembangan Test Driven: Cara yang baik / diterima untuk menguji operasi sistem file?

14

Saya sedang mengerjakan proyek saat ini yang menghasilkan tabel (antara lain) berdasarkan isi dari sistem file, dan pada gilirannya melakukan beberapa modifikasi meta-data pada hal-hal yang ditemukannya. Pertanyaannya adalah: bagaimana tes harus ditulis tentang ini, atau mengatur? Apakah ada cara mudah untuk mengejek ini? Atau haruskah saya menyiapkan "kotak pasir"?

Kirbinator
sumber

Jawaban:

13

Seperti yang selalu Anda lakukan dalam TDD dengan sumber daya eksternal: Anda membuat satu atau lebih antarmuka untuk operasi sistem file Anda dan "mengejeknya". Anda ingin menguji "generator tabel" dan kode modifikasi meta-data Anda, bukan operasi sistem file itu sendiri (kemungkinan besar Anda menggunakan implementasi perpustakaan siap pakai untuk mengakses sistem file).

Doc Brown
sumber
TDD tidak merekomendasikan mengejek implementasi unit yang sedang diuji. Lihat (e, g) solnic.eu/2014/05/22/mocking-and-ruby.html
soru
1
@soru: Bukan itu yang direkomendasikan jawaban ini. Ini merekomendasikan pertama membuat antarmuka, lalu mengejek antarmuka . Jadi Anda menguji logika bisnis, tetapi bukan antarmuka sistem file.
sleske
5
Tapi sepertinya logika bisnis didefinisikan dalam hal file dan direktori. Jadi hal-hal yang memanggil sistem file API adalah hal-hal yang perlu diuji. Menguji logika bisnis non-file terkait tidak perlu mengejek; coba saja.
soru
@ Ya benar, jadi Anda membuat lapisan tipis di sekitar file & folder dengan antarmuka yang ditentukan sedemikian rupa sehingga semua operasi domain-spesifik berada di sisi klien, dan sisi implementasi sepele untuk yakin itu berfungsi tanpa pengujian unit (uji integrasi akan masih diperlukan). Mirip dengan gagasan Dialog Humble dalam kode ui, atau menggunakan Repositori tiruan dalam kode yang beroperasi pada objek yang persisten.
Jules
2
Jadi secara efektif kami mengundurkan diri dari pengujian kelas aktual yang berinteraksi dengan sistem file, database, dll ... alih-alih kami membuat implementasi yang berbeda dengan antarmuka yang sama dengan mock / stub, tetapi kelas sebenarnya yang kami tinggalkan tanpa jenis pengujian unit, karena kami percaya bahwa kami tidak dapat mengujinya dan harus melakukan pengujian integrasi untuk mengujinya. Apakah ini benar?
Andrew Savinykh
11

Apa yang salah dengan memiliki sistem file "test"?

Buat folder template / struktur direktori yang memiliki cukup konten untuk menguji operasi Anda.

Selama pengaturan unit tes Anda salin struktur awal ini (akan merekomendasikan Anda ZIP templat dan unzip ke area pengujian Anda). Jalankan tes Anda. Hapus semuanya saat meruntuhkan.

Masalah dengan mengejek adalah pertama-tama sistem file, OS dan database milik proyek Anda tidak benar-benar memenuhi syarat sebagai sumber daya eksternal dan kedua mengejek panggilan sistem tingkat rendah adalah memakan waktu dan rentan kesalahan.

James Anderson
sumber
5
Mengejek operasi sistem file akan membuat banyak (!) Menjalankan tes lebih cepat daripada menggunakan sistem file nyata, dan jika ini lebih "rawan kesalahan" masih bisa diperdebatkan, saya akan mengatakan itu tergantung pada implementasi. Namun demikian saya pikir saran Anda baik-baik saja untuk membuat tes integrasi otomatis (yang biasanya saya lakukan pertama kali ketika tidak melakukan TDD). Tetapi OP secara khusus meminta TDD, dan tes unit TDD harus cepat.
Doc Brown
1
Saya pikir sistem file, jika diejek, idealnya harus memiliki seluruh API yang ditulis dan dikelola oleh beberapa kelompok, karena Anda menciptakan kembali roda, jika Anda melakukan sesuatu yang signifikan dengan sistem file.
Frank Hileman
2
@ Doc Brown - Saya agak berasumsi dia ingin melakukan dir, menghapus, dan mengubah nama jenis operasi yang semuanya memiliki kasus tepi yang akan menyakitkan untuk dipermainkan. Juga pada perangkat keras modern yang membuka ritsleting beberapa file kecil ke direktori hanya sedikit lebih lambat daripada memuat kelas Java - itu semua IO setelah semua.
James Anderson
Semakin saya memikirkan sistem file tes, semakin saya menyukainya.
Frank Hileman
3

Ini adalah jenis hal yang Anda perlu uji integrasi, karena sistem file dunia nyata memiliki semua jenis perilaku aneh (seperti cara Windows tidak akan membiarkan menghapus file jika ada proses, termasuk deleter, buka).

Jadi pendekatan TDD adalah menulis tes integrasi terlebih dahulu (TDD, sebenarnya, tidak memiliki konsep 'tes unit' dan 'tes integrasi' yang berbeda; mereka hanya tes). Sangat mungkin itu sudah cukup; begitu pekerjaan selesai, hentikan, pulanglah .

Jika tidak, akan ada beberapa kompleksitas internal yang tidak mudah diuji secara memadai dengan mengatur file. Dalam hal ini, Anda cukup mengeluarkan kompleksitas itu, memasukkannya ke dalam kelas, dan menulis unit test untuk kelas itu . Sangat mungkin Anda akan menemukan bahwa kelas umum dapat digunakan dalam kasus database, xml, dll.

Dalam kasus apa pun Anda tidak akan mengambil inti mendasar dari kode yang Anda tulis dan 'mengejeknya' untuk menulis tes yang akan lulus apakah unit yang diuji salah atau tidak.

soru
sumber
Jawaban ini benar-benar meletakkannya dalam perspektif untuk saya - 'unit test' and 'integration test'; they are just tests.saya pikir secara realistis, ini akan menjadi solusi terbaik untuk kasus saya - saya benar-benar perlu menguji perpustakaan sistem file yang saya gunakan untuk kasus tepi, dan bagaimana aplikasi harus menanggapi itu. Jika saya beralih ke pustaka sistem file yang berbeda, saya tidak ingin harus menulis ulang sekelompok mengejek / kode uji untuk bekerja dengan pustaka baru, tetapi memiliki struktur folder tes dan tes integrasi akan membuatnya lebih sederhana.
tehDorf
2

Saya memahami pertanyaan Anda sebagai "Cara yang baik / diterima untuk menguji kelas yang tergantung pada operasi sistem file". Saya tidak berasumsi bahwa Anda ingin menguji sistem file os Anda.

Untuk menjaga upaya untuk 'antarmuka ke operasi sistem file Anda dan "mengejek mereka"' sebagai jawaban @ Doc Brown disarankan sekecil mungkin itu adalah ide yang baik untuk menggunakan aliran biner java atau pembaca teks (atau ada yang setara dalam c # atau bahasa pemrograman yang Anda gunakan) alih-alih menggunakan File dengan nama file langsung di kelas tdd-dikembangkan.

Contoh:

Menggunakan java, saya telah mengimplementasikan CsvReader kelas

public class CsvReader {
    private Reader reader;

    public CsvReader(Reader reader) {
        this.reader = reader;
    }
}

Untuk pengujian saya menggunakan data memori seperti ini

String contentOfCsv = "TestColumn1;TestColumn2\n"+
    "value1;value2\n";

CsvReader sut = new CsvReader(java.io.StringReader(contentOfCsv));

atau embel testdata ke sumber daya

CsvReader sut = new CsvReader(getClass().getResourceAsStream("/data.csv"));

Dalam produksi saya menggunakan sistem file

CsvReader sut = new CsvReader(new BufferedReader( new FileReader( "/import/Prices.csv" ) ));

Dengan cara ini CsvReader saya tidak bergantung pada sistem file tetapi pada abstraksi "Pembaca" di mana ada implementasi untuk sistem file.

k3b
sumber
2
Satu-satunya masalah di sini adalah bahwa OP tidak berbicara tentang operasi file, tetapi operasi sistem file dan operasi meta data - saya kira dia berarti sesuatu seperti daftar semua file dalam direktori, memperbarui beberapa informasi EXIF ​​di semua file gambar dll.
Doc Brown
Ini benar.
Kirbinator
1
Anda dapat membuat IDirectoryLister yang memiliki metode String [] Daftar (Direktori string); maka FakeDirectoryLister dapat mengimplementasikan metode itu dengan mengembalikan String [] {".", "..", "foo.bat", "bar.exe"};
Anders Lindén
0

Buat pembungkus untuk operasi sistem file. Dalam pengujian, berikan tiruan yang mengimplementasikan antarmuka yang sama dengan pembungkus. Dalam produksi, sampaikan bungkusnya.

jewewlett
sumber