Skip to content

test: exhaustive pytest coverage#50

Merged
deacon-mp merged 2 commits intomasterfrom
test/exhaustive-pytest-coverage
Mar 18, 2026
Merged

test: exhaustive pytest coverage#50
deacon-mp merged 2 commits intomasterfrom
test/exhaustive-pytest-coverage

Conversation

@deacon-mp
Copy link
Copy Markdown
Contributor

Summary

  • Expands pytest test suite for all atomic plugin modules (143 tests total)
  • Adds tests for powershell parser (including the known list() bug on checked_flags)
  • Covers ability ingestion, command concatenation, GUI endpoints, hook enable/disable
  • Adds shared conftest.py with fixtures and Caldera dependency stubs
  • Adds pytest.ini configuration

Modules covered

  • app/atomic_svc.py — 100+ tests covering all public/private methods
  • app/atomic_gui.py — initialization and service wiring tests
  • app/parsers/atomic_powershell.py — parser logic and known bug documentation
  • hook.py — module attributes and enable() function

Test plan

  • Run pytest tests/ -v to verify all tests pass

Generated with Claude Code

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Expands the plugin’s pytest suite to cover the Atomic plugin’s service layer, GUI wiring, PowerShell parser behavior, and hook module behavior, while adding shared fixtures/stubs to run tests without a full Caldera runtime.

Changes:

  • Added comprehensive unit tests for AtomicService, AtomicGUI, hook.enable(), and the PowerShell parser.
  • Introduced tests/conftest.py to provide shared fixtures and Caldera dependency stubs.
  • Added pytest.ini to standardize pytest discovery and asyncio behavior.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/test_hook.py Adds async tests for hook.enable() and module attribute assertions
tests/test_atomic_svc.py Adds broad unit coverage for AtomicService helpers and ingestion flow
tests/test_atomic_powershell.py Adds tests documenting current parser behavior (including known bug)
tests/test_atomic_gui.py Adds basic initialization/inheritance tests for AtomicGUI
tests/conftest.py Adds shared fixtures and stubs to decouple tests from Caldera
pytest.ini Configures pytest discovery and asyncio mode

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +160 to +165
def generate_dummy_payload():
with open(DUMMY_PAYLOAD_PATH, 'w') as f:
f.write(DUMMY_PAYLOAD_CONTENT)
yield DUMMY_PAYLOAD_PATH
if os.path.exists(DUMMY_PAYLOAD_PATH):
os.remove(DUMMY_PAYLOAD_PATH)
Comment on lines +112 to 119
def test_handle_attachment(self, atomic_svc, generate_dummy_payload, tmp_path):
atomic_svc.payloads_dir = str(tmp_path / 'payloads')
os.makedirs(atomic_svc.payloads_dir, exist_ok=True)
target_hash = hashlib.md5(DUMMY_PAYLOAD_CONTENT.encode()).hexdigest()
target_name = target_hash[:PREFIX_HASH_LENGTH] + '_dummyatomicpayload'
target_path = atomic_svc.payloads_dir + '/' + target_name
target_path = os.path.join(atomic_svc.payloads_dir, target_name)
assert atomic_svc._handle_attachment(DUMMY_PAYLOAD_PATH) == target_name
assert os.path.isfile(target_path)
Comment on lines +6 to +33
class TestParserCheckedFlags:
"""
Tests for the Parser.checked_flags class attribute.

KNOWN BUG: `list('FullyQualifiedErrorId')` produces a list of individual
characters ['F', 'u', 'l', 'l', 'y', ...] instead of the intended
['FullyQualifiedErrorId']. This means the parser checks for single
characters rather than the full error string.
"""

def test_checked_flags_is_list(self):
assert isinstance(Parser.checked_flags, list)

def test_checked_flags_known_bug_individual_characters(self):
"""
Demonstrates the known bug: list('FullyQualifiedErrorId') splits the
string into individual characters instead of wrapping it in a list.
"""
expected_buggy = list('FullyQualifiedErrorId')
assert Parser.checked_flags == expected_buggy
# This is what it SHOULD be:
expected_correct = ['FullyQualifiedErrorId']
assert Parser.checked_flags != expected_correct

def test_checked_flags_length_is_wrong(self):
"""The list has 21 entries (one per char) instead of 1."""
assert len(Parser.checked_flags) == len('FullyQualifiedErrorId')
assert len(Parser.checked_flags) != 1
Comment on lines +49 to +51
patch('os.listdir', return_value=['abilities', 'other']):
await hook.enable(services)
# If abilities already exists, no cloning or populating should happen
Comment on lines +120 to +124
with patch.object(hook, 'data_dir', '/tmp/atomic_test_hook_data'), \
patch('os.listdir', return_value=['abilities']), \
patch('hook.AtomicGUI'):
await hook.enable(services)
_ = mock_app_svc.application # verify it was accessed
@deacon-mp
Copy link
Copy Markdown
Contributor Author

@copilot review

Copy link
Copy Markdown

Copilot AI commented Mar 18, 2026

@deacon-mp I've opened a new pull request, #57, to work on those changes. Once the pull request is ready, I'll request review from you.

- conftest.py: generate_dummy_payload uses tmp_path fixture instead of
  hard-coded /tmp path; cleanup is now handled automatically by pytest
- test_atomic_svc.py: attachment tests use fixture-returned path instead
  of the module-level DUMMY_PAYLOAD_PATH constant
- test_atomic_powershell.py: mark checked_flags tests as xfail since they
  assert current buggy behavior (list() splitting string into chars) and
  will break once the underlying bug is fixed
- test_hook.py: test_enable_creates_gui now patches hook.AtomicGUI and
  asserts it was called with expected args; test_enable_accesses_app uses
  PropertyMock for mock_app_svc.application and asserts it was accessed
@deacon-mp deacon-mp force-pushed the test/exhaustive-pytest-coverage branch from 74e5e0f to 9a2085c Compare March 18, 2026 13:29
@deacon-mp deacon-mp merged commit 9411303 into master Mar 18, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants