@@ -9,6 +9,8 @@ The libtmux pytest plugin provides powerful fixtures for testing tmux-related fu
9
9
Testing a simple server connection:
10
10
11
11
``` python
12
+ import libtmux
13
+
12
14
def test_server_connection (server ):
13
15
""" Test that we can connect to a tmux server."""
14
16
assert server is not None
@@ -20,6 +22,8 @@ def test_server_connection(server):
20
22
Testing session creation and properties:
21
23
22
24
``` python
25
+ import libtmux
26
+
23
27
def test_new_session (session ):
24
28
""" Test that the session fixture provides a working session."""
25
29
assert session is not None
@@ -38,6 +42,9 @@ def test_new_session(session):
38
42
Testing window creation and manipulation:
39
43
40
44
``` python
45
+ import libtmux
46
+ from libtmux.constants import PaneDirection
47
+
41
48
def test_window_operations (session ):
42
49
""" Test window creation and properties."""
43
50
# Create a new window
@@ -49,7 +56,7 @@ def test_window_operations(session):
49
56
assert window.window_name == " renamed_window"
50
57
51
58
# Split the window
52
- pane = window.split_window( )
59
+ pane = window.split( direction = PaneDirection.Right )
53
60
assert len (window.panes) == 2
54
61
55
62
# Send keys to pane
@@ -67,6 +74,9 @@ def test_window_operations(session):
67
74
Testing pane creation and interaction:
68
75
69
76
``` python
77
+ import libtmux
78
+ from libtmux.constants import PaneDirection
79
+
70
80
def test_pane_operations (pane ):
71
81
""" Test operations on a pane fixture."""
72
82
# Send a command
@@ -81,7 +91,7 @@ def test_pane_operations(pane):
81
91
assert any (" Testing pane operations" in line for line in output)
82
92
83
93
# Split the pane
84
- new_pane = pane.split_window( )
94
+ new_pane = pane.split( direction = PaneDirection.Below )
85
95
assert new_pane is not None
86
96
87
97
# Verify we have two panes now
@@ -94,6 +104,8 @@ def test_pane_operations(pane):
94
104
Setting up a specific environment for tests:
95
105
96
106
``` python
107
+ import libtmux
108
+
97
109
def test_with_custom_environment (server ):
98
110
""" Test with a customized environment setup."""
99
111
# Create a session with specific options
@@ -116,7 +128,7 @@ def test_with_custom_environment(server):
116
128
117
129
# Test window switching
118
130
custom_session.switch_window(1 )
119
- current = custom_session.attached_window
131
+ current = custom_session.active_window
120
132
assert current.window_name == " window2"
121
133
122
134
# Clean up
@@ -132,6 +144,8 @@ def test_with_custom_environment(server):
132
144
Handling commands that take time to execute:
133
145
134
146
``` python
147
+ import libtmux
148
+
135
149
def test_long_running_command (pane ):
136
150
""" Test interaction with long-running commands."""
137
151
# Start a command that will run for a few seconds
@@ -158,6 +172,8 @@ def test_long_running_command(pane):
158
172
Testing integration with other terminal programs:
159
173
160
174
``` python
175
+ import libtmux
176
+
161
177
def test_program_integration (pane ):
162
178
""" Test interaction with another terminal program."""
163
179
# Start a text editor (nano is simple and widely available)
@@ -195,6 +211,8 @@ def test_program_integration(pane):
195
211
Testing error handling:
196
212
197
213
``` python
214
+ import libtmux
215
+
198
216
def test_error_handling (pane ):
199
217
""" Test handling of command errors."""
200
218
# Send a command that will fail
@@ -217,6 +235,7 @@ Using pytest parametrization with tmux fixtures:
217
235
218
236
``` python
219
237
import pytest
238
+ import libtmux
220
239
221
240
@pytest.mark.parametrize (" window_name" , [" test1" , " test2" , " test3" ])
222
241
def test_multiple_windows (session , window_name ):
@@ -225,7 +244,7 @@ def test_multiple_windows(session, window_name):
225
244
assert window.window_name == window_name
226
245
227
246
# Do something with each window
228
- pane = window.attached_pane
247
+ pane = window.active_pane
229
248
pane.send_keys(f " echo 'Testing window { window_name} ' " , enter = True )
230
249
231
250
# Verify output
@@ -248,6 +267,8 @@ def test_multiple_windows(session, window_name):
248
267
If you're having trouble with your tmux tests, try these techniques:
249
268
250
269
``` python
270
+ import libtmux
271
+
251
272
def test_with_debugging (pane ):
252
273
""" Example showing debugging techniques."""
253
274
# Capture initial state
@@ -279,3 +300,241 @@ def test_with_debugging(pane):
279
300
print (f " Failed to find ' { expected_text} ' in output: { output} " )
280
301
assert any (expected_text in line for line in output)
281
302
```
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