Commit 898d5c22 authored by Adrian Wuillemet's avatar Adrian Wuillemet
Browse files

#65 Add in some test cases

parent 8272ff01
#!/usr/bin/env python
import unittest
import beads.modules.reader as reader
from modules.errors import ParsingError
from io import BytesIO, TextIOWrapper
class BeadsParsingTest(unittest.TestCase):
"""
Test class to test correct handling of .bead files
"""
def test_correct_file_content(self):
"""
Test that a correct file content can be parsed without error
"""
self.maxDiff = None
content_lines: bytes = \
b"A:Transition_1:B\n"\
b"A:Transition_2:C\n"\
b"B:Transition_1:D\n"\
b"B:Transition_3:A\n"\
b"C:Transition_4:B"
wrapper: TextIOWrapper = TextIOWrapper(BytesIO(content_lines))
expected: dict = {
'name': 'graph',
'nodes': [
{'id': 'A'},
{'id': 'B'},
{'id': 'C'},
{'id': 'D'}
],
'transitions': [
{'label': 'Transition_1', 'from': 'A', 'to': 'B'},
{'label': 'Transition_2', 'from': 'A', 'to': 'C'},
{'label': 'Transition_1', 'from': 'B', 'to': 'D'},
{'label': 'Transition_3', 'from': 'B', 'to': 'A'},
{'label': 'Transition_4', 'from': 'C', 'to': 'B'}
]
}
actual: dict = reader.parse_beads(wrapper)
self.assertEqual(actual, expected)
def test_config_can_be_parsed(self):
"""
Test that a correct file content can be parsed without error
"""
self.maxDiff = None
content_lines: bytes = \
b"#! name:GRAPH start:C\n"\
b"A:Transition_1:B\n"\
b"A:Transition_2:C\n"\
b"B:Transition_1:D\n"\
b"B:Transition_3:A\n"\
b"C:Transition_4:B"
wrapper: TextIOWrapper = TextIOWrapper(BytesIO(content_lines))
expected: dict = {
'name': 'GRAPH',
'nodes': [
{'id': 'A'},
{'id': 'B'},
{'id': 'C', "start": True},
{'id': 'D'}
],
'transitions': [
{'label': 'Transition_1', 'from': 'A', 'to': 'B'},
{'label': 'Transition_2', 'from': 'A', 'to': 'C'},
{'label': 'Transition_1', 'from': 'B', 'to': 'D'},
{'label': 'Transition_3', 'from': 'B', 'to': 'A'},
{'label': 'Transition_4', 'from': 'C', 'to': 'B'}
]
}
actual: dict = reader.parse_beads(wrapper)
self.assertEqual(actual, expected)
def test_config_ignores_unsupported_values(self):
"""
Test that a correct file content can be parsed without error
"""
self.maxDiff = None
content_lines: bytes = \
b"#! title:GRAPH beginning:C\n"\
b"A:Transition_1:B\n"\
b"A:Transition_2:C\n"\
b"B:Transition_1:D\n"\
b"B:Transition_3:A\n"\
b"C:Transition_4:B"
wrapper: TextIOWrapper = TextIOWrapper(BytesIO(content_lines))
expected: dict = {
'name': 'graph',
'nodes': [
{'id': 'A'},
{'id': 'B'},
{'id': 'C'},
{'id': 'D'}
],
'transitions': [
{'label': 'Transition_1', 'from': 'A', 'to': 'B'},
{'label': 'Transition_2', 'from': 'A', 'to': 'C'},
{'label': 'Transition_1', 'from': 'B', 'to': 'D'},
{'label': 'Transition_3', 'from': 'B', 'to': 'A'},
{'label': 'Transition_4', 'from': 'C', 'to': 'B'}
]
}
actual: dict = reader.parse_beads(wrapper)
self.assertEqual(actual, expected)
def test_parsing_handles_whitespaces_correct(self):
"""
Test that a correct file content can be parsed without error
"""
self.maxDiff = None
content_lines: bytes = \
b"A :Transition_1 :B\n"\
b"A: Transition_2: C\n"\
b"B : Transition_1 : D\n"\
b"B : Transition_3 : A\n"\
b"C: Transition_4 :B"
wrapper: TextIOWrapper = TextIOWrapper(BytesIO(content_lines))
expected: dict = {
'name': 'graph',
'nodes': [
{'id': 'A'},
{'id': 'B'},
{'id': 'C'},
{'id': 'D'}
],
'transitions': [
{'label': 'Transition_1', 'from': 'A', 'to': 'B'},
{'label': 'Transition_2', 'from': 'A', 'to': 'C'},
{'label': 'Transition_1', 'from': 'B', 'to': 'D'},
{'label': 'Transition_3', 'from': 'B', 'to': 'A'},
{'label': 'Transition_4', 'from': 'C', 'to': 'B'}
]
}
actual: dict = reader.parse_beads(wrapper)
self.assertEqual(actual, expected)
def test_parsing_does_not_allow_nonalpha_characters(self):
"""
Test that a correct file content can be parsed without error
"""
self.maxDiff = None
content_lines: bytes = \
b"A:Transition_1:B\n"\
b"A:Transition_2:!C\n"\
wrapper: TextIOWrapper = TextIOWrapper(BytesIO(content_lines))
self.assertRaises(ParsingError, lambda: reader.parse_beads(wrapper))
#!/usr/bin/env python
import unittest
class TestTest(unittest.TestCase):
def test_test(self):
self.assertEqual("Python Code","Python Code")
#!/usr/bin/env python3
import unittest
import modules.validator as val
from modules.errors import ValidationError
class ValidationTest(unittest.TestCase):
"""
Class to test the internal validation of state machine logic.
Rudimentary test coverage for common cases.
"""
def test_a_valid_machine(self):
"""
Test that a valid machine does not raise any errors on inspection.
"""
correct_machine: dict = {
"name": "correct machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{"id": "B"},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
val.inspect(correct_machine)
self.assertTrue(True)
def test_invalid_machine_with_missing_name(self):
"""
Test that a missing name key raises a Validation error.
"""
invalid_machine: dict = {
# no name
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{"id": "B"},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
self.assertRaises(ValidationError, lambda: val.inspect(invalid_machine))
def test_invalid_machine_with_missing_nodes(self):
"""
Test that a missing nodes key raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
# no nodes
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
self.assertRaises(ValidationError, lambda: val.inspect(invalid_machine))
def test_invalid_machine_with_missing_transitions(self):
"""
Test that a missing transitions key raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{"id": "B"},
]
# no transitions
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_empty_nodes(self):
"""
Test that no declared node raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
# empty nodes
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_empty_transitions(self):
"""
Test that no declared transition raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{"id": "B"},
],
"transitions": [
# empty transitions
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_node_missing_id(self):
"""
Test that a node with missing id key raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{
# empty node
},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_duplicate_nodes(self):
"""
Test that a duplicate node declaration raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{
# duplicate id
"id": "C"
},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_transitions_missing_keys(self):
"""
Test that a duplicate node declaration raises a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
{"id": "B"},
],
"transitions": [
# missing 'label'
{"from": "A", "to": "B"},
# missing 'to'
{"from": "A", "label": "Transition2"},
# missing 'from'
{"label": "Transition1", "to": "C"},
# missing all required keys
{},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_multiple_start_nodes(self):
"""
Test that multiple start nodes raise a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "C"},
{"id": "A", "start": True},
# second start node
{"id": "B", "start": True},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "C"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_unreachable_nodes(self):
"""
Test that unreachable nodes raise a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "A", "start": True},
{"id": "B"},
# unreachable nodes C and D
{"id": "C"},
{"id": "D"}
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "B", "label": "Transition1", "to": "B"},
{"from": "A", "label": "Transition2", "to": "A"},
# only transition references of C and D
{"from": "C", "label": "Transition3", "to": "D"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_duplicate_transitions(self):
"""
Test that nodes that are referenced by the same transition multiple times as from node raise a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "A", "start": True},
{"id": "B"},
{"id": "C"},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "B", "label": "Transition1", "to": "C"},
# second time Transition1 references A as from node
{"from": "A", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_undeclared_node_reference(self):
"""
Test that a reference to an undeclared node raise a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "A", "start": True},
{"id": "B"},
{"id": "C"},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
# transitions that references the undeclared node D
{"from": "A", "label": "Transition4", "to": "D"},
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
def test_invalid_machine_with_misspelled_node_reference(self):
"""
Test that misspelled references to nodes raise a Validation error.
"""
invalid_machine: dict = {
"name": "invalid machine",
"nodes": [
{"id": "A", "start": True},
{"id": "B"},
{"id": "C"},
],
"transitions": [
{"from": "A", "label": "Transition1", "to": "B"},
{"from": "B", "label": "Transition1", "to": "C"},
{"from": "C", "label": "Transition3", "to": "A"},
# transitions that references the undeclared node 'b' instead of 'B'
{"from": "b", "label": "Transition2", "to": "A"}
]
}
with self.assertRaises(ValidationError):
val.inspect(invalid_machine)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment