test_gerber_flow.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import sys
  2. import unittest
  3. from PyQt5 import QtGui, QtWidgets
  4. from FlatCAMApp import App, tclCommands
  5. from FlatCAMObj import FlatCAMGerber, FlatCAMGeometry, FlatCAMCNCjob
  6. from flatcamGUI.ObjectUI import GerberObjectUI, GeometryObjectUI
  7. from time import sleep
  8. import os
  9. import tempfile
  10. class GerberFlowTestCase(unittest.TestCase):
  11. """
  12. This is a top-level test covering the Gerber-to-GCode
  13. generation workflow.
  14. THIS IS A REQUIRED TEST FOR ANY UPDATES.
  15. """
  16. filename = 'simple1.gbr'
  17. def setUp(self):
  18. self.app = QtWidgets.QApplication(sys.argv)
  19. # Create App, keep app defaults (do not load
  20. # user-defined defaults).
  21. self.fc = App(user_defaults=False)
  22. self.fc.open_gerber('tests/gerber_files/' + self.filename)
  23. def tearDown(self):
  24. del self.fc
  25. del self.app
  26. def test_flow(self):
  27. # Names of available objects.
  28. names = self.fc.collection.get_names()
  29. print(names)
  30. # --------------------------------------
  31. # Total of 1 objects.
  32. # --------------------------------------
  33. self.assertEqual(len(names), 1,
  34. "Expected 1 object, found %d" % len(names))
  35. # --------------------------------------
  36. # Object's name matches the file name.
  37. # --------------------------------------
  38. self.assertEqual(names[0], self.filename,
  39. "Expected name == %s, got %s" % (self.filename, names[0]))
  40. # ---------------------------------------
  41. # Get object by that name, make sure it's a FlatCAMGerber.
  42. # ---------------------------------------
  43. gerber_name = names[0]
  44. gerber_obj = self.fc.collection.get_by_name(gerber_name)
  45. self.assertTrue(isinstance(gerber_obj, FlatCAMGerber),
  46. "Expected FlatCAMGerber, instead, %s is %s" %
  47. (gerber_name, type(gerber_obj)))
  48. # ----------------------------------------
  49. # Object's GUI matches Object's options
  50. # ----------------------------------------
  51. # TODO: Open GUI with double-click on object.
  52. # Opens the Object's GUI, populates it.
  53. gerber_obj.build_ui()
  54. for option, value in list(gerber_obj.options.items()):
  55. try:
  56. form_field = gerber_obj.form_fields[option]
  57. except KeyError:
  58. print(("**********************************************************\n"
  59. "* WARNING: Option '{}' has no form field\n"
  60. "**********************************************************"
  61. "".format(option)))
  62. continue
  63. self.assertEqual(value, form_field.get_value(),
  64. "Option '{}' == {} but form has {}".format(
  65. option, value, form_field.get_value()
  66. ))
  67. # --------------------------------------------------
  68. # Changes in the GUI should be read in when
  69. # running any process. Changing something here.
  70. # --------------------------------------------------
  71. form_field = gerber_obj.form_fields['isotooldia']
  72. value = form_field.get_value()
  73. form_field.set_value(value * 1.1) # Increase by 10%
  74. print(("'isotooldia' == {}".format(value)))
  75. # --------------------------------------------------
  76. # Create isolation routing using default values
  77. # and by clicking on the button.
  78. # --------------------------------------------------
  79. # Get the object's GUI and click on "Generate Geometry" under
  80. # "Isolation Routing"
  81. assert isinstance(gerber_obj, FlatCAMGerber) # Just for the IDE
  82. # Changed: UI has been build already
  83. #gerber_obj.build_ui() # Open the object's UI.
  84. ui = gerber_obj.ui
  85. assert isinstance(ui, GerberObjectUI)
  86. ui.generate_iso_button.click() # Click
  87. # ---------------------------------------------
  88. # Check that GUI has been read in.
  89. # ---------------------------------------------
  90. value = gerber_obj.options['isotooldia']
  91. form_value = form_field.get_value()
  92. self.assertEqual(value, form_value,
  93. "Form value for '{}' == {} was not read into options"
  94. "which has {}".format('isotooldia', form_value, value))
  95. print(("'isotooldia' == {}".format(value)))
  96. # ---------------------------------------------
  97. # Check that only 1 object has been created.
  98. # ---------------------------------------------
  99. names = self.fc.collection.get_names()
  100. self.assertEqual(len(names), 2,
  101. "Expected 2 objects, found %d" % len(names))
  102. # -------------------------------------------------------
  103. # Make sure the Geometry Object has the correct name
  104. # -------------------------------------------------------
  105. geo_name = gerber_name + "_iso"
  106. self.assertTrue(geo_name in names,
  107. "Object named %s not found." % geo_name)
  108. # -------------------------------------------------------
  109. # Get the object make sure it's a geometry object
  110. # -------------------------------------------------------
  111. geo_obj = self.fc.collection.get_by_name(geo_name)
  112. self.assertTrue(isinstance(geo_obj, FlatCAMGeometry),
  113. "Expected a FlatCAMGeometry, got %s" % type(geo_obj))
  114. # ------------------------------------
  115. # Open the UI, make CNCObject
  116. # ------------------------------------
  117. geo_obj.build_ui()
  118. ui = geo_obj.ui
  119. assert isinstance(ui, GeometryObjectUI) # Just for the IDE
  120. ui.generate_cnc_button.click() # Click
  121. # Work is done in a separate thread and results are
  122. # passed via events to the main event loop which is
  123. # not running. Run only for pending events.
  124. #
  125. # I'm not sure why, but running it only once does
  126. # not catch the new object. Might be a timing issue.
  127. # http://pyqt.sourceforge.net/Docs/PyQt4/qeventloop.html#details
  128. for _ in range(2):
  129. sleep(0.1)
  130. self.app.processEvents()
  131. # ---------------------------------------------
  132. # Check that only 1 object has been created.
  133. # ---------------------------------------------
  134. names = self.fc.collection.get_names()
  135. self.assertEqual(len(names), 3,
  136. "Expected 3 objects, found %d" % len(names))
  137. # -------------------------------------------------------
  138. # Make sure the CNC Job Object has the correct name
  139. # -------------------------------------------------------
  140. cnc_name = geo_name + "_cnc"
  141. self.assertTrue(cnc_name in names,
  142. "Object named %s not found." % geo_name)
  143. # -------------------------------------------------------
  144. # Get the object make sure it's a CNC Job object
  145. # -------------------------------------------------------
  146. cnc_obj = self.fc.collection.get_by_name(cnc_name)
  147. self.assertTrue(isinstance(cnc_obj, FlatCAMCNCjob),
  148. "Expected a FlatCAMCNCJob, got %s" % type(geo_obj))
  149. # -----------------------------------------
  150. # Export G-Code, check output
  151. # -----------------------------------------
  152. assert isinstance(cnc_obj, FlatCAMCNCjob)
  153. output_filename = ""
  154. # get system temporary file(try create it and delete also)
  155. with tempfile.NamedTemporaryFile(prefix='unittest.',
  156. suffix="." + cnc_name + '.gcode',
  157. delete=True) as tmp_file:
  158. output_filename = tmp_file.name
  159. cnc_obj.export_gcode(output_filename)
  160. self.assertTrue(os.path.isfile(output_filename))
  161. os.remove(output_filename)
  162. print(names)