Pencerahan: Melakukan Aksi / Trigger Wizard di Unit Test Odoo
Diposting pada 28 Jun 2026, 14:10
Ditanyakan oleh: Kurniawan
Halo teman-teman praktisi Odoo sekalian, salam kenal saya Kurniawan.
Saya sedang mendalami pengembangan modul kustom di Odoo dan ingin meningkatkan kualitasnya dengan unit testing. Nah, yang menjadi kendala saat ini adalah bagaimana cara terbaik untuk mensimulasikan 'aksi' yang biasanya dilakukan oleh pengguna secara langsung di UI, tapi ini dilakukan dalam konteks unit test?
Contohnya, saya ingin menguji sebuah skenario di mana user mengklik tombol 'Validate' pada suatu dokumen, atau mengisi data di wizard lalu menekan tombol 'Apply'. Aksi-aksi ini kan seringkali memicu logic bisnis atau perubahan status dokumen. Saya ingin memastikan semua logic tersebut berjalan sesuai ekspektasi di dalam script unit test saya.
Apakah ada metode standar atau best practice yang biasa teman-teman pakai untuk memicu action-action semacam ini (baik itu button click, confirm wizard, dsb.) di dalam unit test Odoo? Mungkin ada yang bisa share pengalaman atau potongan kode sederhana? Sangat butuh pencerahannya nih dari yang sudah lebih dulu berkecimpung. Terima kasih banyak sebelumnya!
Admin Odoo ForumAdmin & AI Support28 Jun 2026, 14:11
Halo Mas Kurniawan, salam kenal juga!
Wah, ini pertanyaan yang bagus sekali dan sering menjadi "PR" bagi kita yang mendalami unit testing di Odoo. Mas Kurniawan sudah di jalur yang benar untuk meningkatkan kualitas modul. Mensimulasikan aksi UI di unit test memang krusial untuk memastikan logic bisnis berjalan sesuai harapan.
Secara umum, ada dua pendekatan utama untuk mensimulasikan "klik tombol" atau interaksi wizard dalam unit test Odoo, dan untungnya, ini cukup standar dan straightforward.
### 1. Mensimulasikan Klik Tombol (Direct Method Call)
Kebanyakan tombol di Odoo yang memicu aksi langsung pada suatu dokumen (misalnya tombol 'Validate', 'Confirm', 'Cancel') sebenarnya terhubung ke sebuah metode (function) di model Python yang terkait. Jadi, cara terbaik untuk mensimulasikannya dalam unit test adalah dengan memanggil langsung metode tersebut pada recordset yang sedang kita uji.
Misalnya, jika ada tombol 'Validate' di model `sale.order` yang memanggil metode `action_confirm()`, maka di unit test kita tinggal panggil saja `sale_order_record.action_confirm()`.
Contoh Kode:
Misalnya kita punya model `my.document` dengan field `state` dan tombol `action_validate` yang mengubah state dari 'draft' ke 'validated'.
```python
from odoo.tests.common import TransactionCase, Form
from odoo import fields
class TestMyDocument(TransactionCase):
def setUp(self, args, kwargs):
super().setUp(args, kwargs)
# Persiapan data awal untuk test
self.document = self.env['my.document'].create({
'name': 'Dokumen Uji Coba',
'state': 'draft',
# tambahkan field lain yang diperlukan
})
def test_document_validation(self):
# Pastikan state awal adalah 'draft'
self.assertEqual(self.document.state, 'draft')
# >>> SIMULASI KLIK TOMBOL 'VALIDATE' <<<
# Panggil langsung metode yang terhubung ke tombol
self.document.action_validate()
# Verifikasi hasilnya
self.assertEqual(self.document.state, 'validated')
# Anda bisa menambahkan verifikasi lain,
# misalnya apakah ada log activity yang terbuat,
# atau apakah field lain ikut berubah.
self.assertTrue(self.document.validated_by.id == self.env.user.id) # Contoh: field validated_by otomatis terisi
```
Dalam contoh di atas, `self.document.action_validate()` adalah inti dari simulasi klik tombol.
### 2. Mensimulasikan Interaksi Wizard (Create & Call Action)
Wizard sedikit lebih kompleks karena melibatkan interaksi dengan model transient (sementara). Prosesnya biasanya melibatkan:
1. Membuat instance dari model wizard.
2. Mengisi field-field di wizard (jika ada input yang diperlukan).
3. Memanggil metode aksi yang ada di wizard (misalnya `button_confirm`, `apply`, `action_process`).
Penting juga untuk memastikan konteks (context) yang benar saat membuat atau memanggil wizard, terutama jika wizard tersebut bergantung pada `active_id` atau `active_ids` dari recordset yang sedang aktif di UI.
Contoh Kode:
Misalnya, kita ingin menguji wizard 'Register Payment' (`account.payment.register`) pada sebuah Invoice.
```python
from odoo.tests.common import TransactionCase, Form
from odoo import fields
class TestInvoicePaymentWizard(TransactionCase):
def setUp(self, args, kwargs):
super().setUp(args, kwargs)
# Persiapan data dasar: partner, produk, journal
self.partner = self.env['res.partner'].create({'name': 'Test Partner'})
self.product = self.env['product.product'].create({'name': 'Test Product', 'list_price': 100.0})
self.bank_journal = self.env['account.journal'].create({
'name': 'Bank Test',
'type': 'bank',
'code': 'BNKT',
'currency_id': self.env.company.currency_id.id,
})
# Temukan payment method line yang sesuai
self.payment_method_line = self.env['account.payment.method.line'].search([
('payment_method_id.code', '=', 'manual'), # Contoh 'manual' untuk pembayaran manual
('journal_id', '=', self.bank_journal.id)
], limit=1)
if not self.payment_method_line:
self.fail("No suitable payment method line found for manual payments.")
def test_register_payment_wizard(self):
# Buat invoice yang akan dibayar
invoice = self.env['account.move'].create({
'move_type': 'out_invoice',
'partner_id': self.partner.id,
'invoice_date': fields.Date.today(),
'journal_id': self.env['account.journal'].search([('type', '=', 'sale')], limit=1).id,
})
invoice.invoice_line_ids = [(0, 0, {
'product_id': self.product.id,
'quantity': 1,
'price_unit': 100.0,
})]
invoice.action_post() # Post invoice agar bisa dibayar
# Pastikan state awal invoice belum terbayar
self.assertEqual(invoice.payment_state, 'not_paid')
# >>> SIMULASI INTERAKSI WIZARD 'REGISTER PAYMENT' <<<
# 1. Buat instance wizard. Penting: sertakan context active_model dan active_ids!
wizard = self.env['account.payment.register'].with_context(
active_model='account.move',
active_ids=invoice.ids
).create({
'amount': 100.0, # Isi field jumlah pembayaran
'payment_date': fields.Date.today(),
'journal_id': self.bank_journal.id,
'payment_method_line_id': self.payment_method_line.id,
})
# 2. Panggil metode aksi wizard (misalnya 'action_create_payments')
wizard.action_create_payments()
# Verifikasi hasilnya
self.assertEqual(invoice.payment_state, 'paid')
self.assertEqual(invoice.amount_residual, 0.0)
# Anda bisa juga memverifikasi apakah record payment baru terbuat
payment = self.env['account.payment'].search([('ref', '=', invoice.name)], limit=1)
self.assertTrue(payment)
self.assertEqual(payment.amount, 100.0)
```
Dalam contoh wizard, baris `wizard = self.env['account.payment.register'].with_context(...)` dan `wizard.action_create_payments()` adalah kuncinya. Perhatikan bagaimana kita memberikan `active_model` dan `active_ids` di konteks, karena wizard `account.payment.register` bergantung pada informasi ini untuk mengetahui invoice mana yang sedang diproses.
### Best Practice Tambahan:
Persiapan Data: Pastikan semua data yang dibutuhkan oleh logic bisnis (misalnya user, company, product, partner, journal) sudah disiapkan di metode `setUp` atau langsung di dalam test case.
Konteks: Selalu perhatikan apakah ada `context` khusus yang perlu dilewatkan, terutama untuk aksi yang bergantung pada `active_id`, `active_ids`, atau konfigurasi khusus. Anda bisa menggunakan `self.env['model.name'].with_context(your_context)` atau `recordset.with_context(your_context).method_call()`.
Assertions: Setelah memicu aksi, selalu tambahkan `self.assertEqual()`, `self.assertTrue()`, atau `self.assertFalse()` untuk memverifikasi bahwa perubahan yang diharapkan benar-benar terjadi. Ini adalah inti dari unit test!
Kelas `Form`: Untuk interaksi yang lebih kompleks, terutama saat mengisi banyak field di UI yang memiliki default value atau onchange logic, Anda bisa juga menggunakan objek `Form` dari `odoo.tests.common`. Namun, untuk aksi tombol dan wizard sederhana, pendekatan di atas biasanya sudah cukup.
Semoga pencerahan ini membantu Mas Kurniawan dalam meningkatkan kualitas unit test di Odoo! Selamat berkarya!