test_large_state.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. """Test large state."""
  2. import time
  3. import jinja2
  4. import pytest
  5. from selenium.webdriver.common.by import By
  6. from reflex.testing import AppHarness, WebDriver
  7. LARGE_STATE_APP_TEMPLATE = """
  8. import reflex as rx
  9. class State(rx.State):
  10. var0: int = 0
  11. {% for i in range(1, var_count) %}
  12. var{{ i }}: str = "{{ i }}" * 10000
  13. {% endfor %}
  14. def increment_var0(self):
  15. self.var0 += 1
  16. def index() -> rx.Component:
  17. return rx.box(rx.button(State.var0, on_click=State.increment_var0, id="button"))
  18. app = rx.App()
  19. app.add_page(index)
  20. """
  21. def get_driver(large_state) -> WebDriver:
  22. """Get an instance of the browser open to the large_state app.
  23. Args:
  24. large_state: harness for LargeState app
  25. Returns:
  26. WebDriver instance.
  27. """
  28. assert large_state.app_instance is not None, "app is not running"
  29. return large_state.frontend()
  30. @pytest.mark.parametrize("var_count", [1, 10, 100, 1000, 10000])
  31. def test_large_state(var_count: int, tmp_path_factory, benchmark):
  32. """Measure how long it takes for button click => state update to round trip.
  33. Args:
  34. var_count: number of variables to store in the state
  35. tmp_path_factory: pytest fixture
  36. benchmark: pytest fixture
  37. Raises:
  38. TimeoutError: if the state doesn't update within 30 seconds
  39. """
  40. template = jinja2.Template(LARGE_STATE_APP_TEMPLATE)
  41. large_state_rendered = template.render(var_count=var_count)
  42. with AppHarness.create(
  43. root=tmp_path_factory.mktemp(f"large_state"),
  44. app_source=large_state_rendered,
  45. app_name="large_state",
  46. ) as large_state:
  47. driver = get_driver(large_state)
  48. try:
  49. assert large_state.app_instance is not None
  50. button = driver.find_element(By.ID, "button")
  51. t = time.time()
  52. while button.text != "0":
  53. time.sleep(0.1)
  54. if time.time() - t > 30.0:
  55. raise TimeoutError("Timeout waiting for initial state")
  56. times_clicked = 0
  57. def round_trip(clicks: int, timeout: float):
  58. t = time.time()
  59. for _ in range(clicks):
  60. button.click()
  61. nonlocal times_clicked
  62. times_clicked += clicks
  63. while button.text != str(times_clicked):
  64. time.sleep(0.005)
  65. if time.time() - t > timeout:
  66. raise TimeoutError("Timeout waiting for state update")
  67. benchmark(round_trip, clicks=10, timeout=30.0)
  68. finally:
  69. driver.quit()