Testing ERPNext or apps on Frappe Framework will be a-bit confusing because of each doctype will have dependencies and it a-bit hard to understand for newcomers (and for me).
So here is my attempt to explain or understand it.
First of all you will need to create new site just for testing and allow test on that site.
# create new testing site
bench new-site testing.apps --mariadb-root-password 12345 --admin-password admin
# allow test on testing site
bench --site testing.apps set-config allow_tests true
# install custom app if needed
bench --site testing.apps install-app your_app
Then you will be good to go to write testing file, follow testing document from frappe.
https://frappeframework.com/docs/user/en/testing#writing-tests
A-bit more clarification on test file.
-
setUp
andtearDown
is method from unittest.TestCase, it will be run once per test-
setUp
will be run before running test method -
tearDown
will be run after running test, whether test method succeeded or not
-
-
test_dependencies
(list of doctype name) vairable will be use to define dependencies doctype -
test_record
will be test record in dict format, normally frappe will usefrappe.get_test_records
then store test record intest_records.json
file -
test_dependencies
ortest_record
won’t work outside doctype test file.
Running test
More command can be seen at testing document as link above.
bench --site testing.apps --verbose run-tests --app frappe
bench --site testing.apps --verbose run-tests --app your_app
bench --site testing.apps --verbose run-tests --module frappe.tests.test_api
Miscellaneous
- If some thing not working as expected, you might want to reset testing site first before start to debugging.
bench --site testing.apps --force reinstall --mariadb-root-password 12345 --yes --admin-password admin
- You could run testing site, to see how test record are created.
bench --site testing.apps start
- When writing test, if the record are created you should delete that record so you could run the test multiple time. Adding
frappe.db.rollback()
totearDown
will rollback database after each test.
def tearDown(self):
frappe.db.rollback()`
- It’ll be a good idea to add before_test function and use that to complete setup wizard.
def before_tests():
# complete setup if missing
if not int(frappe.db.get_single_value('System Settings', 'setup_complete') or 0):
setup_complete({
'language': 'English',
'email': 'testing@test.co',
'full_name': 'Taster',
'password': 'tastyTestTaste',
'country': 'Thailand',
'timezone': 'Asia/Bangkok',
'currency': 'THB',
})
frappe.db.commit()
frappe.clear_cache()
- For testing outside of doctype test, and testing need to get record from doctype you could do it on setUp function
from frappe.test_runner import make_test_records
class TestBlogQuery(unittest.TestCase):
def setUp(self):
make_test_records(
doctype='Blog Post',
verbose=frappe.flags.print_messages,
force=True,
)
def tearDown(self):
pass
def test_get_blog_list(self):
Overview Testing flow
Here is how testing works.
- Click command run-test >
frappe.commands.utils.run_tests
- Run
frappe.test_runner.main
- Run before_test function from hook.py
- Run test [All test / For module / For doctype]
- Test will create dependent record based on link fields and
test_dependencies
variable in each test file >frappe.test_runner.get_dependencies
- From test_dependencies it’ll create test records >
frappe.test_runner.make_test_records_for_doctype
- From
test_records
variable in test file, which frappe normally usefrappe.get_test_records
function to get test records or it’ll create test record from it’s own doctype -
frappe.get_test_records
will get test records which store intest_records.json
file in each doctype folder - Create test object from test_records using
frappe.test_runner.make_test_objects
, it’ll skip if record is already exist
- From
- Test will create dependent record based on link fields and