Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 
 
 

241 wiersze
6.9 KiB

  1. # Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
  2. # MIT License. See license.txt
  3. from __future__ import unicode_literals
  4. import frappe
  5. import unittest, json
  6. import importlib
  7. from frappe.modules import load_doctype_module, get_module_name
  8. from frappe.utils import cstr
  9. def main(app=None, module=None, doctype=None, verbose=False, tests=(), force=False):
  10. frappe.flags.print_messages = verbose
  11. frappe.flags.in_test = True
  12. if not frappe.db:
  13. frappe.connect()
  14. if not frappe.conf.get("db_name").startswith("test_"):
  15. raise Exception, 'db_name must start with "test_"'
  16. # workaround! since there is no separate test db
  17. frappe.clear_cache()
  18. if verbose:
  19. print 'Running "before_tests" hooks'
  20. for fn in frappe.get_hooks("before_tests", app_name=app):
  21. frappe.get_attr(fn)()
  22. if doctype:
  23. ret = run_tests_for_doctype(doctype, verbose=verbose, tests=tests, force=force)
  24. elif module:
  25. ret = run_tests_for_module(module, verbose=verbose, tests=tests)
  26. else:
  27. ret = run_all_tests(app, verbose)
  28. frappe.db.commit()
  29. # workaround! since there is no separate test db
  30. frappe.clear_cache()
  31. return ret
  32. def run_all_tests(app=None, verbose=False):
  33. import os
  34. apps = [app] if app else frappe.get_installed_apps()
  35. test_suite = unittest.TestSuite()
  36. for app in apps:
  37. for path, folders, files in os.walk(frappe.get_pymodule_path(app)):
  38. for dontwalk in ('locals', '.git', 'public'):
  39. if dontwalk in folders:
  40. folders.remove(dontwalk)
  41. # print path
  42. for filename in files:
  43. filename = cstr(filename)
  44. if filename.startswith("test_") and filename.endswith(".py"):
  45. # print filename[:-3]
  46. _add_test(path, filename, verbose, test_suite=test_suite)
  47. return unittest.TextTestRunner(verbosity=1+(verbose and 1 or 0)).run(test_suite)
  48. def run_tests_for_doctype(doctype, verbose=False, tests=(), force=False):
  49. module = frappe.db.get_value("DocType", doctype, "module")
  50. test_module = get_module_name(doctype, module, "test_")
  51. if force:
  52. for name in frappe.db.sql_list("select name from `tab%s`" % doctype):
  53. frappe.delete_doc(doctype, name, force=True)
  54. make_test_records(doctype, verbose=verbose, force=force)
  55. module = frappe.get_module(test_module)
  56. return _run_unittest(module, verbose=verbose, tests=tests)
  57. def run_tests_for_module(module, verbose=False, tests=()):
  58. module = importlib.import_module(module)
  59. if hasattr(module, "test_dependencies"):
  60. for doctype in module.test_dependencies:
  61. make_test_records(doctype, verbose=verbose)
  62. return _run_unittest(module=module, verbose=verbose, tests=tests)
  63. def _run_unittest(module, verbose=False, tests=()):
  64. test_suite = unittest.TestSuite()
  65. module_test_cases = unittest.TestLoader().loadTestsFromModule(module)
  66. if tests:
  67. for each in module_test_cases:
  68. for test_case in each.__dict__["_tests"]:
  69. if test_case.__dict__["_testMethodName"] in tests:
  70. test_suite.addTest(test_case)
  71. else:
  72. test_suite.addTest(module_test_cases)
  73. return unittest.TextTestRunner(verbosity=1+(verbose and 1 or 0)).run(test_suite)
  74. def _add_test(path, filename, verbose, test_suite=None):
  75. import os, imp
  76. if os.path.sep.join(["doctype", "doctype", "boilerplate"]) in path:
  77. # in /doctype/doctype/boilerplate/
  78. return
  79. if not test_suite:
  80. test_suite = unittest.TestSuite()
  81. if os.path.basename(os.path.dirname(path))=="doctype":
  82. txt_file = os.path.join(path, filename[5:].replace(".py", ".json"))
  83. with open(txt_file, 'r') as f:
  84. doc = json.loads(f.read())
  85. doctype = doc["name"]
  86. make_test_records(doctype, verbose)
  87. module = imp.load_source(filename[:-3], os.path.join(path, filename))
  88. test_suite.addTest(unittest.TestLoader().loadTestsFromModule(module))
  89. def make_test_records(doctype, verbose=0, force=False):
  90. frappe.flags.mute_emails = True
  91. if not frappe.db:
  92. frappe.connect()
  93. for options in get_dependencies(doctype):
  94. if options == "[Select]":
  95. continue
  96. if options not in frappe.local.test_objects:
  97. frappe.local.test_objects[options] = []
  98. make_test_records(options, verbose, force)
  99. make_test_records_for_doctype(options, verbose, force)
  100. def get_modules(doctype):
  101. module = frappe.db.get_value("DocType", doctype, "module")
  102. try:
  103. test_module = load_doctype_module(doctype, module, "test_")
  104. if test_module:
  105. reload(test_module)
  106. except ImportError:
  107. test_module = None
  108. return module, test_module
  109. def get_dependencies(doctype):
  110. module, test_module = get_modules(doctype)
  111. meta = frappe.get_meta(doctype)
  112. link_fields = meta.get_link_fields()
  113. for df in meta.get_table_fields():
  114. link_fields.extend(frappe.get_meta(df.options).get_link_fields())
  115. options_list = [df.options for df in link_fields] + [doctype]
  116. if hasattr(test_module, "test_dependencies"):
  117. options_list += test_module.test_dependencies
  118. options_list = list(set(options_list))
  119. if hasattr(test_module, "test_ignore"):
  120. for doctype_name in test_module.test_ignore:
  121. if doctype_name in options_list:
  122. options_list.remove(doctype_name)
  123. return options_list
  124. def make_test_records_for_doctype(doctype, verbose=0, force=False):
  125. module, test_module = get_modules(doctype)
  126. if verbose:
  127. print "Making for " + doctype
  128. if hasattr(test_module, "_make_test_records"):
  129. frappe.local.test_objects[doctype] += test_module._make_test_records(verbose)
  130. elif hasattr(test_module, "test_records"):
  131. frappe.local.test_objects[doctype] += make_test_objects(doctype, test_module.test_records, verbose)
  132. else:
  133. test_records = frappe.get_test_records(doctype)
  134. if test_records:
  135. frappe.local.test_objects[doctype] += make_test_objects(doctype, test_records, verbose)
  136. elif verbose:
  137. print_mandatory_fields(doctype)
  138. def make_test_objects(doctype, test_records, verbose=None):
  139. records = []
  140. if not frappe.get_meta(doctype).issingle:
  141. existing = frappe.get_all(doctype, filters={"name":("like", "_T-" + doctype + "-%")})
  142. if existing:
  143. return [d.name for d in existing]
  144. existing = frappe.get_all(doctype, filters={"name":("like", "_Test " + doctype + "%")})
  145. if existing:
  146. return [d.name for d in existing]
  147. for doc in test_records:
  148. if not doc.get("doctype"):
  149. doc["doctype"] = doctype
  150. d = frappe.copy_doc(doc)
  151. if doc.get('name'):
  152. d.name = doc.get('name')
  153. if frappe.local.test_objects.get(d.doctype):
  154. # do not create test records, if already exists
  155. return []
  156. if d.meta.get_field("naming_series"):
  157. if not d.naming_series:
  158. d.naming_series = "_T-" + d.doctype + "-"
  159. # submit if docstatus is set to 1 for test record
  160. docstatus = d.docstatus
  161. d.docstatus = 0
  162. try:
  163. d.insert()
  164. if docstatus == 1:
  165. d.submit()
  166. except frappe.NameError:
  167. pass
  168. records.append(d.name)
  169. frappe.db.commit()
  170. return records
  171. def print_mandatory_fields(doctype):
  172. print "Please setup make_test_records for: " + doctype
  173. print "-" * 60
  174. meta = frappe.get_meta(doctype)
  175. print "Autoname: " + (meta.autoname or "")
  176. print "Mandatory Fields: "
  177. for d in meta.get("fields", {"reqd":1}):
  178. print d.parent + ":" + d.fieldname + " | " + d.fieldtype + " | " + (d.options or "")
  179. print