@@ -9,6 +9,8 @@ The libtmux pytest plugin provides powerful fixtures for testing tmux-related fu
99Testing a simple server connection:
1010
1111``` python
12+ import libtmux
13+
1214def test_server_connection (server ):
1315 """ Test that we can connect to a tmux server."""
1416 assert server is not None
@@ -20,6 +22,8 @@ def test_server_connection(server):
2022Testing session creation and properties:
2123
2224``` python
25+ import libtmux
26+
2327def test_new_session (session ):
2428 """ Test that the session fixture provides a working session."""
2529 assert session is not None
@@ -38,6 +42,9 @@ def test_new_session(session):
3842Testing window creation and manipulation:
3943
4044``` python
45+ import libtmux
46+ from libtmux.constants import PaneDirection
47+
4148def test_window_operations (session ):
4249 """ Test window creation and properties."""
4350 # Create a new window
@@ -49,7 +56,7 @@ def test_window_operations(session):
4956 assert window.window_name == " renamed_window"
5057
5158 # Split the window
52- pane = window.split_window( )
59+ pane = window.split( direction = PaneDirection.Right )
5360 assert len (window.panes) == 2
5461
5562 # Send keys to pane
@@ -67,6 +74,9 @@ def test_window_operations(session):
6774Testing pane creation and interaction:
6875
6976``` python
77+ import libtmux
78+ from libtmux.constants import PaneDirection
79+
7080def test_pane_operations (pane ):
7181 """ Test operations on a pane fixture."""
7282 # Send a command
@@ -81,7 +91,7 @@ def test_pane_operations(pane):
8191 assert any (" Testing pane operations" in line for line in output)
8292
8393 # Split the pane
84- new_pane = pane.split_window( )
94+ new_pane = pane.split( direction = PaneDirection.Below )
8595 assert new_pane is not None
8696
8797 # Verify we have two panes now
@@ -94,6 +104,8 @@ def test_pane_operations(pane):
94104Setting up a specific environment for tests:
95105
96106``` python
107+ import libtmux
108+
97109def test_with_custom_environment (server ):
98110 """ Test with a customized environment setup."""
99111 # Create a session with specific options
@@ -116,7 +128,7 @@ def test_with_custom_environment(server):
116128
117129 # Test window switching
118130 custom_session.switch_window(1 )
119- current = custom_session.attached_window
131+ current = custom_session.active_window
120132 assert current.window_name == " window2"
121133
122134 # Clean up
@@ -132,6 +144,8 @@ def test_with_custom_environment(server):
132144Handling commands that take time to execute:
133145
134146``` python
147+ import libtmux
148+
135149def test_long_running_command (pane ):
136150 """ Test interaction with long-running commands."""
137151 # Start a command that will run for a few seconds
@@ -158,6 +172,8 @@ def test_long_running_command(pane):
158172Testing integration with other terminal programs:
159173
160174``` python
175+ import libtmux
176+
161177def test_program_integration (pane ):
162178 """ Test interaction with another terminal program."""
163179 # Start a text editor (nano is simple and widely available)
@@ -195,6 +211,8 @@ def test_program_integration(pane):
195211Testing error handling:
196212
197213``` python
214+ import libtmux
215+
198216def test_error_handling (pane ):
199217 """ Test handling of command errors."""
200218 # Send a command that will fail
@@ -217,6 +235,7 @@ Using pytest parametrization with tmux fixtures:
217235
218236``` python
219237import pytest
238+ import libtmux
220239
221240@pytest.mark.parametrize (" window_name" , [" test1" , " test2" , " test3" ])
222241def test_multiple_windows (session , window_name ):
@@ -225,7 +244,7 @@ def test_multiple_windows(session, window_name):
225244 assert window.window_name == window_name
226245
227246 # Do something with each window
228- pane = window.attached_pane
247+ pane = window.active_pane
229248 pane.send_keys(f " echo 'Testing window { window_name} ' " , enter = True )
230249
231250 # Verify output
@@ -248,6 +267,8 @@ def test_multiple_windows(session, window_name):
248267If you're having trouble with your tmux tests, try these techniques:
249268
250269``` python
270+ import libtmux
271+
251272def test_with_debugging (pane ):
252273 """ Example showing debugging techniques."""
253274 # Capture initial state
@@ -279,3 +300,241 @@ def test_with_debugging(pane):
279300 print (f " Failed to find ' { expected_text} ' in output: { output} " )
280301 assert any (expected_text in line for line in output)
281302```
303+
304+ ## Testing with Multiple Panes
305+
306+ Testing applications that require multiple panes and interaction between them:
307+
308+ ``` python
309+ import pytest
310+ import libtmux
311+ from libtmux.constants import PaneDirection
312+ import time
313+
314+ def test_multi_pane_interaction (server , session ):
315+ """ Test interaction between multiple panes."""
316+ # Create a window with multiple panes for testing
317+ window = session.new_window(window_name = " multi-pane-test" )
318+
319+ # First pane (already exists as the active pane)
320+ main_pane = window.active_pane
321+
322+ # Create a second pane for output
323+ output_pane = window.split(direction = PaneDirection.Right)
324+
325+ # Create a third pane for monitoring
326+ monitor_pane = main_pane.split(direction = PaneDirection.Below)
327+
328+ # Wait for panes to be ready
329+ time.sleep(0.5 )
330+
331+ # Set up the panes with specific content
332+ main_pane.send_keys(" echo 'This is the main pane'" , enter = True )
333+ output_pane.send_keys(" echo 'This is the output pane'" , enter = True )
334+ monitor_pane.send_keys(" echo 'This is the monitor pane'" , enter = True )
335+
336+ # Create a temporary file in one pane
337+ main_pane.send_keys(" echo 'Shared data' > shared_file.txt" , enter = True )
338+ time.sleep(0.5 )
339+
340+ # Read it from another pane
341+ output_pane.send_keys(" cat shared_file.txt" , enter = True )
342+ time.sleep(0.5 )
343+
344+ # Verify the content was shared
345+ output_content = output_pane.capture_pane()
346+ assert any (" Shared data" in line for line in output_content)
347+
348+ # Use the monitor pane to check the file exists
349+ monitor_pane.send_keys(" ls -la shared_file.txt" , enter = True )
350+ time.sleep(0.5 )
351+
352+ monitor_content = monitor_pane.capture_pane()
353+ assert any (" shared_file.txt" in line for line in monitor_content)
354+
355+ # Clean up
356+ main_pane.send_keys(" rm shared_file.txt" , enter = True )
357+ ```
358+
359+ ## Testing Complex Tmux Configurations
360+
361+ Testing with a custom tmux configuration:
362+
363+ ``` python
364+ import pytest
365+ import libtmux
366+ import pathlib
367+ import tempfile
368+
369+ @pytest.fixture
370+ def custom_config ():
371+ """ Create a temporary tmux configuration file."""
372+ with tempfile.NamedTemporaryFile(mode = ' w+' , suffix = ' .conf' ) as f:
373+ # Write custom tmux configuration
374+ f.write(" # Custom tmux configuration for testing\n " )
375+ f.write(" set -g base-index 1\n " )
376+ f.write(" set -g pane-base-index 1\n " )
377+ f.write(" set -g status-left '[#S] '\n " )
378+ f.write(" set -g status-style bg=green,fg=black\n " )
379+ f.write(" set -g history-limit 5000\n " )
380+ f.flush()
381+ yield pathlib.Path(f.name)
382+
383+ @pytest.fixture
384+ def custom_server (custom_config , TestServer ):
385+ """ Create a server with custom configuration."""
386+ Server = TestServer()
387+ server = Server(config_file = str (custom_config))
388+ yield server
389+ server.kill_server()
390+
391+ def test_with_custom_config (custom_server ):
392+ """ Test tmux with a custom configuration."""
393+ session = custom_server.new_session(session_name = " custom-config-test" )
394+
395+ # Verify custom configuration was applied
396+ options = custom_server.show_options(" g" )
397+
398+ # Check that history limit was set correctly
399+ history_limit = options.get(" history-limit" , " " )
400+ assert history_limit == " 5000"
401+
402+ # Create a window to test base-index
403+ window = session.new_window(window_name = " test-window" )
404+
405+ # In our custom config, the first window should be index 1
406+ window_index = window.get(" window_index" )
407+ assert int (window_index) > 0 , " Custom base-index wasn't applied"
408+ ```
409+
410+ ## Testing with Temporary Files and Directories
411+
412+ Managing temporary files in tests:
413+
414+ ``` python
415+ import pytest
416+ import libtmux
417+ import pathlib
418+ import tempfile
419+ import time
420+
421+ @pytest.fixture
422+ def temp_project_dir ():
423+ """ Create a temporary project directory for testing."""
424+ with tempfile.TemporaryDirectory() as tmpdirname:
425+ project_dir = pathlib.Path(tmpdirname)
426+
427+ # Create some sample files
428+ (project_dir / " main.py" ).write_text(" print('Hello, world!')" )
429+ (project_dir / " README.md" ).write_text(" # Test Project\n\n This is a test project." )
430+ (project_dir / " config.ini" ).write_text(" [settings]\n verbose = true" )
431+
432+ yield project_dir
433+
434+ def test_project_file_manipulation (session , temp_project_dir ):
435+ """ Test working with files in a temporary project directory."""
436+ window = session.new_window(window_name = " file-test" )
437+ pane = window.active_pane
438+
439+ # Navigate to the project directory
440+ pane.send_keys(f " cd { temp_project_dir} " , enter = True )
441+ time.sleep(0.5 )
442+
443+ # List files
444+ pane.send_keys(" ls -la" , enter = True )
445+ time.sleep(0.5 )
446+
447+ # Verify files are visible
448+ output = pane.capture_pane()
449+ assert any (" main.py" in line for line in output)
450+ assert any (" README.md" in line for line in output)
451+
452+ # Run a Python file
453+ pane.send_keys(" python main.py" , enter = True )
454+ time.sleep(0.5 )
455+
456+ # Verify output
457+ output = pane.capture_pane()
458+ assert any (" Hello, world!" in line for line in output)
459+
460+ # Create a new file through tmux
461+ pane.send_keys(" echo 'print(\" Testing is fun\" )' > test.py" , enter = True )
462+ time.sleep(0.5 )
463+
464+ # Run the new file
465+ pane.send_keys(" python test.py" , enter = True )
466+ time.sleep(0.5 )
467+
468+ # Verify output from new file
469+ output = pane.capture_pane()
470+ assert any (" Testing is fun" in line for line in output)
471+ ```
472+
473+ ## Advanced Polling for Command Completion
474+
475+ More robust way to wait for command completion:
476+
477+ ``` python
478+ import pytest
479+ import libtmux
480+ import time
481+ import re
482+
483+ def wait_for_output (pane , expected_pattern , timeout = 5 , interval = 0.1 ):
484+ """
485+ Wait for a specific pattern to appear in the pane output.
486+
487+ Args:
488+ pane: The tmux pane to check
489+ expected_pattern: Regex pattern to look for
490+ timeout: Maximum time to wait in seconds
491+ interval: Time between checks in seconds
492+
493+ Returns:
494+ The matching line if found, None if timeout occurs
495+ """
496+ pattern = re.compile(expected_pattern)
497+ start_time = time.time()
498+
499+ while time.time() - start_time < timeout:
500+ output = pane.capture_pane()
501+
502+ for line in output:
503+ if pattern.search(line):
504+ return line
505+
506+ time.sleep(interval)
507+
508+ return None # Timeout occurred
509+
510+ def test_command_with_polling (session ):
511+ """ Test robust command polling."""
512+ window = session.new_window(window_name = " polling-test" )
513+ pane = window.active_pane
514+
515+ # Start a command that takes time
516+ pane.send_keys(" echo 'Starting'; sleep 2; echo 'Finished!'" , enter = True )
517+
518+ # Wait for command to complete
519+ result = wait_for_output(pane, r " Finished!" )
520+
521+ # Verify command completed successfully
522+ assert result is not None , " Command did not finish within timeout"
523+
524+ # Run a sequence of commands
525+ pane.send_keys(" echo 'Processing step 1'" , enter = True )
526+ assert wait_for_output(pane, r " Processing step 1" )
527+
528+ pane.send_keys(" echo 'Processing step 2'" , enter = True )
529+ assert wait_for_output(pane, r " Processing step 2" )
530+
531+ pane.send_keys(" echo 'Processing step 3'" , enter = True )
532+ assert wait_for_output(pane, r " Processing step 3" )
533+
534+ # Verify order of operations
535+ output = pane.capture_pane()
536+ step1_line = next ((i for i, line in enumerate (output) if " Processing step 1" in line), - 1 )
537+ step2_line = next ((i for i, line in enumerate (output) if " Processing step 2" in line), - 1 )
538+ step3_line = next ((i for i, line in enumerate (output) if " Processing step 3" in line), - 1 )
539+
540+ assert step1_line < step2_line < step3_line, " Commands did not execute in the correct order"
0 commit comments