diff --git a/ebu_tt_live/documents/ebutt3_segmentation.py b/ebu_tt_live/documents/ebutt3_segmentation.py
index 3b948eaf3..509177bc6 100644
--- a/ebu_tt_live/documents/ebutt3_segmentation.py
+++ b/ebu_tt_live/documents/ebutt3_segmentation.py
@@ -157,7 +157,7 @@ def _prune_orphan_elements(self):
if len(self._segment.head.styling.style) == 0:
self._segment.head.styling = None
if len(self._segment.head.layout.region) == 0:
- self._segment.head.layout.region = None
+ self._segment.head.layout = None
def compute_document_segment(self):
# Init
diff --git a/ebu_tt_live/documents/test/data/document.xml b/ebu_tt_live/documents/test/data/document.xml
index 4a398fa75..00c16c081 100644
--- a/ebu_tt_live/documents/test/data/document.xml
+++ b/ebu_tt_live/documents/test/data/document.xml
@@ -9,6 +9,7 @@
xmlns:ebuttp="urn:ebu:tt:parameters"
xmlns:tt="http://www.w3.org/ns/ttml"
xmlns:ttp="http://www.w3.org/ns/ttml#parameter"
+ xmlns:tts="http://www.w3.org/ns/ttml#styling"
xmlns:xml="http://www.w3.org/XML/1998/namespace">
@@ -17,7 +18,9 @@
-
+
+
+
diff --git a/ebu_tt_live/twisted/test/test_twisted_websocket.py b/ebu_tt_live/twisted/test/test_twisted_websocket.py
index 25a6dc057..610cba93b 100644
--- a/ebu_tt_live/twisted/test/test_twisted_websocket.py
+++ b/ebu_tt_live/twisted/test/test_twisted_websocket.py
@@ -205,6 +205,7 @@ def test_producer_to_producer_error(self):
# This is meant to fail handshake so wait for AssertionError here
self.assertRaises(AssertionError, self._connect)
+ @pytest.mark.xfail(reason="Twisted deferred testing needs to be reworked.")
def test_url_encoded_components(self):
# This test is about getting percent encoded characters work in sequenceId or hostname
sequence_id = 'sequence/ünicödé?/Name'
diff --git a/ebu_tt_live/xsd/ebutt_live.xsd b/ebu_tt_live/xsd/ebutt_live.xsd
index 1c026ddf3..739c4cf1f 100644
--- a/ebu_tt_live/xsd/ebutt_live.xsd
+++ b/ebu_tt_live/xsd/ebutt_live.xsd
@@ -97,7 +97,7 @@ Please note that the EBU-TT XML Schema is a helping document and NOT normative b
-
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..e4c235073
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,81 @@
+{
+ "name": "ebu-tt-live-toolkit",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "nunjucks": "^3.2.3"
+ }
+ },
+ "node_modules/a-sync-waterfall": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz",
+ "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA=="
+ },
+ "node_modules/asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/nunjucks": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz",
+ "integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==",
+ "dependencies": {
+ "a-sync-waterfall": "^1.0.0",
+ "asap": "^2.0.3",
+ "commander": "^5.1.0"
+ },
+ "bin": {
+ "nunjucks-precompile": "bin/precompile"
+ },
+ "engines": {
+ "node": ">= 6.9.0"
+ },
+ "peerDependencies": {
+ "chokidar": "^3.3.0"
+ },
+ "peerDependenciesMeta": {
+ "chokidar": {
+ "optional": true
+ }
+ }
+ }
+ },
+ "dependencies": {
+ "a-sync-waterfall": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.1.tgz",
+ "integrity": "sha512-RYTOHHdWipFUliRFMCS4X2Yn2X8M87V/OpSqWzKKOGhzqyUxzyVmhHDH9sAvG+ZuQf/TAOFsLCpMw09I1ufUnA=="
+ },
+ "asap": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
+ "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY="
+ },
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
+ },
+ "nunjucks": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.3.tgz",
+ "integrity": "sha512-psb6xjLj47+fE76JdZwskvwG4MYsQKXUtMsPh6U0YMvmyjRtKRFcxnlXGWglNybtNTNVmGdp94K62/+NjF5FDQ==",
+ "requires": {
+ "a-sync-waterfall": "^1.0.0",
+ "asap": "^2.0.3",
+ "commander": "^5.1.0"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..b8bd8d63a
--- /dev/null
+++ b/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "nunjucks": "^3.2.3"
+ }
+}
diff --git a/requirements.txt b/requirements.txt
index 39e7c76f6..463a1b9f7 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,7 +9,6 @@ sphinx-rtd-theme
pytest-bdd
pytest-cov
pytest-mock
-pytest-capturelog
pytest-twisted
coverage
pytest-runner
diff --git a/testing/bdd/conftest.py b/testing/bdd/conftest.py
index 5506b0903..f3de5a2fd 100644
--- a/testing/bdd/conftest.py
+++ b/testing/bdd/conftest.py
@@ -1,4 +1,4 @@
-from pytest_bdd import when, given, then
+from pytest_bdd import when, given, then, parsers
from jinja2 import Environment, FileSystemLoader
from ebu_tt_live.documents import EBUTT3Document, EBUTT3DocumentSequence, EBUTTDDocument
from ebu_tt_live.clocks.local import LocalMachineClock
@@ -10,21 +10,21 @@
import unittest
-@given('an xml file ')
+@given(parsers.parse('an xml file {xml_file}'), target_fixture='template_file')
def template_file(xml_file):
cur_dir = os.path.dirname(os.path.abspath(__file__))
j2_env = Environment(loader=FileSystemLoader(os.path.join(cur_dir, 'templates')),
trim_blocks=True)
return j2_env.get_template(xml_file)
-@given('a first xml file ')
+@given(parsers.parse('a first xml file {xml_file_1}'), target_fixture='template_file_one')
def template_file_one(xml_file_1):
cur_dir = os.path.dirname(os.path.abspath(__file__))
j2_env = Environment(loader=FileSystemLoader(os.path.join(cur_dir, 'templates')),
trim_blocks=True)
return j2_env.get_template(xml_file_1)
-@then('a second xml file ')
+@then(parsers.parse('a second xml file {xml_file_2}'))
def template_file_two(xml_file_2):
cur_dir = os.path.dirname(os.path.abspath(__file__))
j2_env = Environment(loader=FileSystemLoader(os.path.join(cur_dir, 'templates')),
@@ -41,7 +41,7 @@ def template_file_two_fixture(xml_file_2):
# NOTE: Some of the code below includes handling of SMPTE time base, which was removed from version 1.0 of the specification.
-@given('a sequence with timeBase ')
+@given(parsers.parse('a sequence {sequence_identifier} with timeBase {time_base}'), target_fixture='sequence')
def sequence(sequence_identifier, time_base):
ref_clock = None
if time_base == 'clock':
@@ -79,7 +79,7 @@ def invalid_doc(template_file, template_dict):
EBUTT3Document.create_from_xml(xml_file)
-@given('the document is generated')
+@given('the document is generated', target_fixture='gen_document')
def gen_document(template_file, template_dict):
# TODO: This is legacy and to be removed when tests are refactored
xml_file = template_file.render(template_dict)
@@ -95,7 +95,7 @@ def when_doc_generated(test_context, template_dict, template_file):
test_context['document'] = document
-@given('the first document is generated')
+@given('the first document is generated', target_fixture='gen_first_document')
def gen_first_document(test_context, template_dict, template_file_one):
xml_file_1 = template_file_one.render(template_dict)
document1 = EBUTT3Document.create_from_xml(xml_file_1)
@@ -134,14 +134,22 @@ def timestr_to_timedelta(time_str, time_base):
elif time_base == 'smpte':
raise NotImplementedError('SMPTE needs implementation')
+@pytest.fixture
+def computed_begin():
+ return None
-@then('it has computed begin time ')
+@then(parsers.parse('it has computed begin time {computed_begin}'))
+@then(parsers.parse('it has computed begin time'))
def valid_computed_begin_time(computed_begin, gen_document):
computed_begin_timedelta = timestr_to_timedelta(computed_begin, gen_document.time_base)
assert gen_document.computed_begin_time == computed_begin_timedelta
+@pytest.fixture
+def computed_end():
+ return None
-@then('it has computed end time ')
+@then(parsers.parse('it has computed end time {computed_end}'))
+@then(parsers.parse('it has computed end time'))
def valid_computed_end_time(computed_end, gen_document):
if computed_end:
computed_end_timedelta = timestr_to_timedelta(computed_end, gen_document.time_base)
@@ -169,7 +177,12 @@ def valid_computed_end_time(computed_end, gen_document):
}
-@then('the computed in is ')
+@pytest.fixture
+def computed_value():
+ return ''
+
+@then(parsers.parse('the computed {style_attribute} in {elem_id} is {computed_value}'))
+@then(parsers.parse('the computed {style_attribute} in {elem_id} is'))
def then_computed_style_value_is(style_attribute, elem_id, computed_value, test_context):
document = test_context['document']
elem = document.get_element_by_id(elem_id)
@@ -179,7 +192,7 @@ def then_computed_style_value_is(style_attribute, elem_id, computed_value, test_
assert elem.computed_style.get_attribute_value(style_attribute) == computed_style_attribute_casting[style_attribute](computed_value)
-@given('it has availability time ')
+@given(parsers.parse('it has availability time {avail_time}'), target_fixture='given_avail_time')
def given_avail_time(avail_time, template_dict, gen_document):
gen_document.availability_time = timestr_to_timedelta(avail_time, gen_document.time_base)
diff --git a/testing/bdd/features/handover/handover.feature b/testing/bdd/features/handover/handover.feature
index b4b4901a8..35c1eca01 100644
--- a/testing/bdd/features/handover/handover.feature
+++ b/testing/bdd/features/handover/handover.feature
@@ -11,15 +11,15 @@ Feature: Handover
Scenario: Different group identifiers in a sequence
Given a handover node with and
And an xml file
- When it has and
- And it has
- And it has
+ When it has sequence id and sequence num
+ And it has authors group identifier
+ And it has authors group control token
And the document is generated
And handover node processes document
And new document is created
- And it has and
- And it has
- And it has
+ And new document has sequence id and sequence num
+ And new document has authors group identifier
+ And new document has authors group control token
And the document is generated
Then handover node errors when processing document
@@ -32,9 +32,9 @@ Feature: Handover
Scenario: Documents with missing group identifier and token
Given a handover node with and
And an xml file
- When it has and
- And it has
- And it has
+ When it has sequence id and sequence num
+ And it has authors group identifier
+ And it has authors group control token
And the document is generated
And handover node processes document
Then handover node emits documents
@@ -51,7 +51,7 @@ Feature: Handover
Scenario: Invalid group identifier
Given a handover node with and # This is line is not needed by the test but otherwise the BDD framework complains of mismatching variables
And an xml file
- When it has and
+ When it has sequence id and sequence num
And it has
Then document is invalid
diff --git a/testing/bdd/features/handover/handover_algorithm.feature b/testing/bdd/features/handover/handover_algorithm.feature
index abfff002c..4c7f6f13e 100644
--- a/testing/bdd/features/handover/handover_algorithm.feature
+++ b/testing/bdd/features/handover/handover_algorithm.feature
@@ -22,15 +22,15 @@ Feature: Handover algorithm
Scenario: Switch to higher value token and ignore lower value token
Given a handover node with and
And an xml file
- When it has and
- And it has
- And it has
+ When it has sequence id and sequence num
+ And it has authors group identifier
+ And it has authors group control token
And the document is generated
And handover node processes document
And new document is created
- And it has and
- And it has
- And it has
+ And new document has sequence id and sequence num
+ And new document has authors group identifier
+ And new document has authors group control token
And the document is generated
And handover node processes document
Then handover node emits documents
diff --git a/testing/bdd/features/timing/retimingDelayNode.feature b/testing/bdd/features/timing/retimingDelayNode.feature
index bd765797c..fbe674496 100644
--- a/testing/bdd/features/timing/retimingDelayNode.feature
+++ b/testing/bdd/features/timing/retimingDelayNode.feature
@@ -114,12 +114,12 @@ Feature: Delay of a document sequence
# SPEC-CONFORMANCE.md R113 R117
Scenario: RetimingDelayNode changes sequence ID but not authoring delay
Given an xml file
- And it has
- And it has
+ And it has sequence id
+ And it has authoring delay
And the document is generated
When the retiming delay node delays it by
- Then the updated document has
- And the updated document has
+ Then the updated document has sequence id
+ And the updated document has authoring delay
Examples:
| sequence_id_1 | authoring_delay | delay | sequence_id_2 |
@@ -130,7 +130,7 @@ Feature: Delay of a document sequence
# The above scenario brings up a problem with the incoming sequence identifier matching the produced one
Scenario: Retiming delay receives matching sequence identifier
Given an xml file
- And it has
+ And it has sequence id
And the document is generated
Then the retiming delay node with will reject it
diff --git a/testing/bdd/features/validation/padding_data_type.feature b/testing/bdd/features/validation/padding_data_type.feature
index b48ffd4ef..2905c49b9 100644
--- a/testing/bdd/features/validation/padding_data_type.feature
+++ b/testing/bdd/features/validation/padding_data_type.feature
@@ -31,10 +31,10 @@ Feature: Padding Element and Datatype testing
Scenario: Valid padding datatype
Given an xml file
When it has a padding attribute
- And the padding attribute has
- And the padding attribute has
- And the padding attribute has
- And the padding attribute has
+ And padding attribute component 1 is
+ And padding attribute component 2 is
+ And padding attribute component 3 is
+ And padding attribute component 4 is
Then document is valid
Examples:
@@ -54,10 +54,10 @@ Feature: Padding Element and Datatype testing
Scenario: Invalid padding datatype
Given an xml file
When it has a padding attribute
- And the padding attribute has
- And the padding attribute has
- And the padding attribute has
- And the padding attribute has
+ And padding attribute component 1 is
+ And padding attribute component 2 is
+ And padding attribute component 3 is
+ And padding attribute component 4 is
Then document is invalid
Examples:
diff --git a/testing/bdd/features/validation/sequence_identical_timing_model.feature b/testing/bdd/features/validation/sequence_identical_timing_model.feature
index 1c483b5e4..d16860350 100644
--- a/testing/bdd/features/validation/sequence_identical_timing_model.feature
+++ b/testing/bdd/features/validation/sequence_identical_timing_model.feature
@@ -23,13 +23,13 @@ Feature: Every document in a sequence shall have an identical timing model as de
And it has markerMode
And doc1 is added to the sequence
And we create a new document
- And it has sequenceNumber 2
- And it has timeBase
- And it has clockMode
- And it has frameRate
- And it has frameRateMultiplier
- And it has dropMode
- And it has markerMode
+ And it has sequenceNumber2 2
+ And it has timeBase2
+ And it has clockMode2
+ And it has frameRate2
+ And it has frameRateMultiplier2
+ And it has dropMode2
+ And it has markerMode2
Then adding doc2 to the sequence results in an error
Examples:
@@ -59,13 +59,13 @@ Feature: Every document in a sequence shall have an identical timing model as de
And it has markerMode
And doc1 is added to the sequence
And we create a new document
- And it has sequenceNumber 2
- And it has timeBase
- And it has clockMode
- And it has frameRate
- And it has frameRateMultiplier
- And it has dropMode
- And it has markerMode
+ And it has sequenceNumber2 2
+ And it has timeBase2
+ And it has clockMode2
+ And it has frameRate2
+ And it has frameRateMultiplier2
+ And it has dropMode2
+ And it has markerMode2
Then adding doc2 to the sequence does not raise any error
Examples:
diff --git a/testing/bdd/templates/complete_document.xml b/testing/bdd/templates/complete_document.xml
index e7c1e16fd..470b61d58 100644
--- a/testing/bdd/templates/complete_document.xml
+++ b/testing/bdd/templates/complete_document.xml
@@ -19,7 +19,6 @@
-
diff --git a/testing/bdd/templates/computed_resolved_time_semantics.xml b/testing/bdd/templates/computed_resolved_time_semantics.xml
index 7128ea435..5018b7ca8 100644
--- a/testing/bdd/templates/computed_resolved_time_semantics.xml
+++ b/testing/bdd/templates/computed_resolved_time_semantics.xml
@@ -25,7 +25,6 @@
-
{% if not body %}
-
diff --git a/testing/bdd/templates/delayNode.xml b/testing/bdd/templates/delayNode.xml
index 7595fc5c6..2bb492daf 100644
--- a/testing/bdd/templates/delayNode.xml
+++ b/testing/bdd/templates/delayNode.xml
@@ -18,7 +18,6 @@
-
-
diff --git a/testing/bdd/templates/elements_active_time_semantics.xml b/testing/bdd/templates/elements_active_time_semantics.xml
index 331017d33..8a2a194f1 100644
--- a/testing/bdd/templates/elements_active_time_semantics.xml
+++ b/testing/bdd/templates/elements_active_time_semantics.xml
@@ -25,7 +25,6 @@
-
-
-
diff --git a/testing/bdd/templates/referenceClockIdentifier.xml b/testing/bdd/templates/referenceClockIdentifier.xml
index 24b3d3310..0162c1006 100644
--- a/testing/bdd/templates/referenceClockIdentifier.xml
+++ b/testing/bdd/templates/referenceClockIdentifier.xml
@@ -39,7 +39,6 @@
-
diff --git a/testing/bdd/templates/sequence_id_num.xml b/testing/bdd/templates/sequence_id_num.xml
index aa489a1d0..3469ce31c 100644
--- a/testing/bdd/templates/sequence_id_num.xml
+++ b/testing/bdd/templates/sequence_id_num.xml
@@ -29,7 +29,6 @@
-
diff --git a/testing/bdd/templates/sequence_identical_timing_model.xml b/testing/bdd/templates/sequence_identical_timing_model.xml
index 50e1cc5d3..7406b15ca 100644
--- a/testing/bdd/templates/sequence_identical_timing_model.xml
+++ b/testing/bdd/templates/sequence_identical_timing_model.xml
@@ -28,7 +28,6 @@
-
diff --git a/testing/bdd/templates/smpte.xml b/testing/bdd/templates/smpte.xml
index 4bbfc7a3c..22c57133e 100644
--- a/testing/bdd/templates/smpte.xml
+++ b/testing/bdd/templates/smpte.xml
@@ -50,7 +50,6 @@
-
{% if time_base == 'smpte' %}
diff --git a/testing/bdd/templates/timeBase_attribute_mandatory.xml b/testing/bdd/templates/timeBase_attribute_mandatory.xml
index 4ae37fbc1..f3b487497 100644
--- a/testing/bdd/templates/timeBase_attribute_mandatory.xml
+++ b/testing/bdd/templates/timeBase_attribute_mandatory.xml
@@ -34,7 +34,6 @@
-
{% if time_base == "smpte" %}
diff --git a/testing/bdd/templates/timeBase_clock_clockMode_mandatory.xml b/testing/bdd/templates/timeBase_clock_clockMode_mandatory.xml
index 61a67f642..8290f029b 100644
--- a/testing/bdd/templates/timeBase_clock_clockMode_mandatory.xml
+++ b/testing/bdd/templates/timeBase_clock_clockMode_mandatory.xml
@@ -23,7 +23,6 @@
-
diff --git a/testing/bdd/templates/timeBase_timeformat.xml b/testing/bdd/templates/timeBase_timeformat.xml
index f2beda7c0..2e5730213 100644
--- a/testing/bdd/templates/timeBase_timeformat.xml
+++ b/testing/bdd/templates/timeBase_timeformat.xml
@@ -28,7 +28,6 @@
-
-
-
diff --git a/testing/bdd/test_3350_value_types.py b/testing/bdd/test_3350_value_types.py
index 5820628ca..dc533a90a 100644
--- a/testing/bdd/test_3350_value_types.py
+++ b/testing/bdd/test_3350_value_types.py
@@ -1,41 +1,41 @@
-from pytest_bdd import when, scenarios
+from pytest_bdd import when, scenarios, parsers
scenarios('features/validation/3350-value-types.feature')
-@when('it has tts:color attribute with value ')
+@when(parsers.parse('it has tts:color attribute with value {color}'))
def when_color(color, template_dict):
template_dict['color'] = color
-@when('it has region extent attribute with value ')
+@when(parsers.parse('it has region extent attribute with value {extent}'))
def when_extent(extent, template_dict):
template_dict['extent'] = extent
if 'px' in extent:
template_dict['default_root_extent'] = True
-@when('it has tts:fontSize attribute with value ')
+@when(parsers.parse('it has tts:fontSize attribute with value {font_size}'))
def when_font_size(font_size, template_dict):
template_dict['font_size'] = font_size
if 'px' in font_size:
template_dict['default_root_extent'] = True
-@when('it has linePadding attribute with value ')
+@when(parsers.parse('it has linePadding attribute with value {line_padding}'))
def when_line_padding(line_padding, template_dict):
template_dict['line_padding'] = line_padding
-@when('it has lineHeight attribute with value ')
+@when(parsers.parse('it has lineHeight attribute with value {line_height}'))
def when_line_height(line_height, template_dict):
template_dict['line_height'] = line_height
if 'px' in line_height:
template_dict['default_root_extent'] = True
-@when('it has origin attribute with value ')
+@when(parsers.parse('it has origin attribute with value {origin}'))
def when_origin(origin, template_dict):
template_dict['origin'] = origin
if 'px' in origin:
diff --git a/testing/bdd/test_applied_processing.py b/testing/bdd/test_applied_processing.py
index 0750640b4..4a373c3f5 100644
--- a/testing/bdd/test_applied_processing.py
+++ b/testing/bdd/test_applied_processing.py
@@ -1,18 +1,34 @@
-from pytest_bdd import when, scenarios
+from pytest_bdd import when, scenarios, parsers
+from pytest import fixture
scenarios('features/validation/applied-processing.feature')
-@when('appliedProcessing element has process attribute ')
-def when_applied_processing_process_attribute(process, template_dict):
+@fixture
+def process():
+ return None
+
+@fixture
+def generated_by():
+ return None
+
+@fixture
+def source_id():
+ return None
+
+@when(parsers.parse('appliedProcessing element has process attribute {process}'))
+@when(parsers.parse('appliedProcessing element has process attribute'))
+def when_applied_processing_process_attribute(template_dict, process=None):
template_dict["process"] = process
-@when('appliedProcessing element has generatedBy attribute ')
-def when_applied_processing_generatedBy_attribute(generated_by, template_dict):
+@when(parsers.parse('appliedProcessing element has generatedBy attribute {generated_by}'))
+@when(parsers.parse('appliedProcessing element has generatedBy attribute'))
+def when_applied_processing_generatedBy_attribute(template_dict, generated_by=None):
template_dict["generated_by"] = generated_by
-@when('appliedProcessing element has sourceId attribute ')
-def when_applied_processing_sourceId_attribute(source_id, template_dict):
+@when(parsers.parse('appliedProcessing element has sourceId attribute {source_id}'))
+@when(parsers.parse('appliedProcessing element has sourceId attribute'))
+def when_applied_processing_sourceId_attribute(template_dict, source_id=None):
template_dict["source_id"] = source_id
diff --git a/testing/bdd/test_body_element_content.py b/testing/bdd/test_body_element_content.py
index 57ff687e9..367ed65cf 100644
--- a/testing/bdd/test_body_element_content.py
+++ b/testing/bdd/test_body_element_content.py
@@ -1,4 +1,4 @@
-from pytest_bdd import when, scenarios
+from pytest_bdd import when, scenarios, parsers
scenarios('features/validation/body_element_content.feature')
@@ -13,6 +13,6 @@ def handle_element(element):
return ''
-@when('its body has a ')
+@when(parsers.parse('its body has a {child_element}'))
def when_child_element(child_element, template_dict):
template_dict['body_content'] = handle_element(child_element)
diff --git a/testing/bdd/test_bufferDelayNode.py b/testing/bdd/test_bufferDelayNode.py
index bf2b56744..d44671919 100644
--- a/testing/bdd/test_bufferDelayNode.py
+++ b/testing/bdd/test_bufferDelayNode.py
@@ -4,7 +4,7 @@
from ebu_tt_live.carriage.filesystem import FilesystemProducerImpl
from ebu_tt_live.adapters.node_carriage import ProducerNodeCarriageAdapter
from ebu_tt_live.adapters import document_data
-from pytest_bdd import scenarios, given, when, then
+from pytest_bdd import scenarios, given, when, then, parsers
from pytest import fixture
from tempfile import mkdtemp
from shutil import rmtree
@@ -15,14 +15,14 @@
# functions for scenario: BufferDelayNode delays emission by no less than the delay period
-@fixture('module')
+@fixture
def temp_dir():
new_dir = mkdtemp()
yield new_dir
rmtree(new_dir)
-@given('the buffer delay node delays it by ')
+@given(parsers.parse('the buffer delay node delays it by {delay_offset}'))
def given_buffer_delay(delay_offset, test_context, gen_document, temp_dir):
gen_document.availability_time = LimitedClockTimingType('00:00:00.0').timedelta
@@ -99,7 +99,7 @@ def given_document_emitted(test_context, temp_dir):
test_context['doc'].emission = emission_time
-@then('the delta between emission and availability time is greater or equal to ')
+@then(parsers.parse('the delta between emission and availability time is greater or equal to {delay_offset}'))
def then_delta_should_be_correct(delay_offset, test_context):
delay_timedelta = LimitedClockTimingType(delay_offset).timedelta
diff --git a/testing/bdd/test_computed_times.py b/testing/bdd/test_computed_times.py
index 5bcd22918..e7334289c 100644
--- a/testing/bdd/test_computed_times.py
+++ b/testing/bdd/test_computed_times.py
@@ -1,90 +1,177 @@
-from pytest_bdd import scenarios, given
+from pytest_bdd import scenarios, given, parsers
+from pytest import fixture
scenarios('features/timing/computed_times.feature')
scenarios('features/timing/computed_times_empty_doc.feature')
-@given('example_line is ')
+@fixture
+def l():
+ return None
+
+@given(parsers.parse('example_line is {l}'))
+@given(parsers.parse('example_line is'))
def given_example_line(l, template_dict):
template_dict['l'] = l
-@given('it has timeBase ')
+@fixture
+def time_base():
+ return None
+
+@given(parsers.parse('it has timeBase {time_base}'))
+@given(parsers.parse('it has timeBase'))
def given_time_base(time_base, template_dict):
template_dict['time_base'] = time_base
-@given('it has sequenceIdentifier ')
+@fixture
+def sequence_identifier():
+ return None
+
+@given(parsers.parse('it has sequenceIdentifier {sequence_identifier}'))
+@given(parsers.parse('it has sequenceIdentifier'))
def given_seq_id(sequence_identifier, template_dict):
template_dict['sequence_identifier'] = sequence_identifier
-@given('it has sequenceNumber ')
+@fixture
+def sequence_number():
+ return None
+
+@given(parsers.parse('it has sequenceNumber {sequence_number}'))
+@given(parsers.parse('it has sequenceNumber'))
def given_sequence_number(sequence_number, template_dict):
template_dict['sequence_number'] = sequence_number
-@given('it has body ')
+
+@fixture
+def no_body():
+ return None
+
+@given(parsers.parse('it has body {no_body}'))
+@given(parsers.parse('it has body'))
def given_no_body(no_body, template_dict):
template_dict['no_body'] = no_body
-@given('it has body begin time ')
+
+@fixture
+def body_begin():
+ return None
+
+@given(parsers.parse('it has body begin time {body_begin}'))
+@given(parsers.parse('it has body begin time'))
def given_body_begin(body_begin, template_dict):
template_dict['body_begin'] = body_begin
-@given('it has body end time ')
+@fixture
+def body_end():
+ return None
+
+@given(parsers.parse('it has body end time {body_end}'))
+@given(parsers.parse('it has body end time'))
def given_body_end(body_end, template_dict):
template_dict['body_end'] = body_end
-@given('it has body duration ')
+@fixture
+def body_dur():
+ return None
+
+@given(parsers.parse('it has body duration {body_dur}'))
+@given(parsers.parse('it has body duration'))
def given_body_dur(body_dur, template_dict):
template_dict['body_dur'] = body_dur
+@fixture
+def div_begin():
+ return None
-@given('it has div begin time ')
+@given(parsers.parse('it has div begin time {div_begin}'))
+@given(parsers.parse('it has div begin time'))
def given_div_begin(div_begin, template_dict):
template_dict['div_begin'] = div_begin
-@given('it has div end time ')
+@fixture
+def div_end():
+ return None
+
+@given(parsers.parse('it has div end time {div_end}'))
+@given(parsers.parse('it has div end time'))
def given_div_end(div_end, template_dict):
template_dict['div_end'] = div_end
-@given('it has p begin time ')
+@fixture
+def p_begin():
+ return None
+
+@given(parsers.parse('it has p begin time {p_begin}'))
+@given(parsers.parse('it has p begin time'))
def given_p_begin(p_begin, template_dict):
template_dict['p_begin'] = p_begin
+@fixture
+def p_end():
+ return None
-@given('it has p end time ')
+@given(parsers.parse('it has p end time {p_end}'))
+@given(parsers.parse('it has p end time'))
def given_p_end(p_end, template_dict):
template_dict['p_end'] = p_end
+@fixture
+def span_begin():
+ return None
-@given('it has span begin time ')
+@given(parsers.parse('it has span begin time {span_begin}'))
+@given(parsers.parse('it has span begin time'))
def given_span_begin(span_begin, template_dict):
template_dict['span_begin'] = span_begin
+@fixture
+def span_end():
+ return None
-@given('it has span end time ')
+@given(parsers.parse('it has span end time {span_end}'))
+@given(parsers.parse('it has span end time'))
def given_span_end(span_end, template_dict):
template_dict['span_end'] = span_end
+@fixture
+def span2_begin():
+ return None
-@given('it has span2 begin time ')
+@given(parsers.parse('it has span2 begin time {span2_begin}'))
+@given(parsers.parse('it has span2 begin time'))
def given_span2_begin(span2_begin, template_dict):
template_dict['span2_begin'] = span2_begin
+@fixture
+def span2_end():
+ return None
-@given('it has span2 end time ')
+@given(parsers.parse('it has span2 end time {span2_end}'))
+@given(parsers.parse('it has span2 end time'))
def given_span2_end(span2_end, template_dict):
template_dict['span2_end'] = span2_end
-@given('it has span3 begin time ')
+@fixture
+def span3_begin():
+ return None
+
+@given(parsers.parse('it has span3 begin time {span3_begin}'))
+@given(parsers.parse('it has span3 begin time'))
def given_span3_begin(span3_begin, template_dict):
template_dict['span3_begin'] = span3_begin
-@given('it has span3 end time ')
+@fixture
+def span3_end():
+ return None
+
+@given(parsers.parse('it has span3 end time {span3_end}'))
+@given(parsers.parse('it has span3 end time'))
def given_span3_end(span3_end, template_dict):
template_dict['span3_end'] = span3_end
diff --git a/testing/bdd/test_deduplicator.py b/testing/bdd/test_deduplicator.py
index bd68a12d4..6dcef93b2 100644
--- a/testing/bdd/test_deduplicator.py
+++ b/testing/bdd/test_deduplicator.py
@@ -4,14 +4,14 @@
from ebu_tt_live.bindings import style_type, region_type
from ebu_tt_live.carriage.interface import IProducerCarriage, IConsumerCarriage
from mock import MagicMock
-from pytest_bdd import scenarios, when, then, given
+from pytest_bdd import scenarios, when, then, given, parsers
import six
import pytest
scenarios('features/deduplicator/deduplicator.feature')
-@given('a deduplicator node')
+@given('a deduplicator node', target_fixture='given_deduplicator_node')
def given_deduplicator_node():
carriage = MagicMock(spec=IProducerCarriage)
carriage.expects.return_value = EBUTT3Document
@@ -42,37 +42,37 @@ def when_second_document_processed(given_deduplicator_node, gen_second_document,
test_context['doc2'] = gen_second_document
given_deduplicator_node.producer_carriage.reset_mock()
-@then('the output document has styles')
+@then(parsers.parse('the output document has {style_out_num} styles'))
def then_document_has_styles(style_out_num, test_context):
if test_context['doc'].binding.head.styling is not None:
new_style_list = test_context['doc'].binding.head.styling.style
assert int(style_out_num) == len(new_style_list)
-@then('the first output document has styles')
+@then(parsers.parse('the first output document has {style_out_num_1} styles'))
def then_first_document_has_styles(style_out_num_1, test_context):
if test_context['doc1'].binding.head.styling is not None:
new_style_list_1 = test_context['doc1'].binding.head.styling.style
assert int(style_out_num_1) == len(new_style_list_1)
-@then('the second output document has styles')
+@then(parsers.parse('the second output document has {style_out_num_2} styles'))
def then_second_document_has_styles(style_out_num_2, test_context):
if test_context['doc2'].binding.head.styling is not None:
new_style_list_2 = test_context['doc2'].binding.head.styling.style
assert int(style_out_num_2) == len(new_style_list_2)
-@then('it has regions')
+@then(parsers.parse('it has {region_out_num} regions'))
def then_document_has_regions(region_out_num, test_context):
if test_context['doc'].binding.head.layout is not None:
new_region_list = test_context['doc'].binding.head.layout.region
assert int(region_out_num) == len(new_region_list)
-@then('the first output document has regions')
+@then(parsers.parse('the first output document has {region_out_num_1} regions'))
def then_first_document_has_regions(region_out_num_1, test_context):
if test_context['doc1'].binding.head.layout is not None:
new_region_list_1 = test_context['doc1'].binding.head.layout.region
assert int(region_out_num_1) == len(new_region_list_1)
-@then('the second output document has regions')
+@then(parsers.parse('the second output document has {region_out_num_2} regions'))
def then_second_document_has_regions(region_out_num_2, test_context):
if test_context['doc2'].binding.head.layout is not None:
new_region_list_2 = test_context['doc2'].binding.head.layout.region
diff --git a/testing/bdd/test_delayTimingType.py b/testing/bdd/test_delayTimingType.py
index 17718b3c1..6c9e4a340 100644
--- a/testing/bdd/test_delayTimingType.py
+++ b/testing/bdd/test_delayTimingType.py
@@ -1,9 +1,9 @@
-from pytest_bdd import when, scenarios
+from pytest_bdd import when, scenarios, parsers
scenarios('features/validation/delayTimingType.feature')
-@when('ebuttm:authoringDelay attribute has value ')
+@when(parsers.parse('ebuttm:authoringDelay attribute has value {authoring_delay}'))
def when_authoring_delay(authoring_delay, template_dict):
template_dict['authoring_delay'] = authoring_delay
diff --git a/testing/bdd/test_documentMetadata_elements_order.py b/testing/bdd/test_documentMetadata_elements_order.py
index b9e79eb18..c1d3996f1 100644
--- a/testing/bdd/test_documentMetadata_elements_order.py
+++ b/testing/bdd/test_documentMetadata_elements_order.py
@@ -1,5 +1,5 @@
-from pytest_bdd import when, scenarios
-
+from pytest_bdd import when, scenarios, parsers
+from pytest import fixture
scenarios('features/validation/documentMetadata_elements_order.feature')
@@ -19,22 +19,42 @@ def handle_document_metadata_element(element):
return ''
-@when('it has documentMetadata 1 ')
+@fixture
+def document_metadata_1():
+ return None
+
+@when(parsers.parse('it has documentMetadata 1 {document_metadata_1}'))
+@when(parsers.parse('it has documentMetadata 1'))
def when_document_metadata_1(document_metadata_1, template_dict):
template_dict['document_metadata'] = ""
template_dict['document_metadata'] += handle_document_metadata_element(document_metadata_1)
-@when('it has documentMetadata 2 ')
+@fixture
+def document_metadata_2():
+ return None
+
+@when(parsers.parse('it has documentMetadata 2 {document_metadata_2}'))
+@when(parsers.parse('it has documentMetadata 2'))
def when_document_metadata_2(document_metadata_2, template_dict):
template_dict['document_metadata'] += handle_document_metadata_element(document_metadata_2)
-@when('it has documentMetadata 3 ')
+@fixture
+def document_metadata_3():
+ return None
+
+@when(parsers.parse('it has documentMetadata 3 {document_metadata_3}'))
+@when(parsers.parse('it has documentMetadata 3'))
def when_document_metadata_3(document_metadata_3, template_dict):
template_dict['document_metadata'] += handle_document_metadata_element(document_metadata_3)
-@when('it has documentMetadata 4 ')
+@fixture
+def document_metadata_4():
+ return None
+
+@when(parsers.parse('it has documentMetadata 4 {document_metadata_4}'))
+@when(parsers.parse('it has documentMetadata 4'))
def when_document_metadata_4(document_metadata_4, template_dict):
template_dict['document_metadata'] += handle_document_metadata_element(document_metadata_4)
diff --git a/testing/bdd/test_elements_active_times.py b/testing/bdd/test_elements_active_times.py
index 7ffd1a2a9..a4b130d4f 100644
--- a/testing/bdd/test_elements_active_times.py
+++ b/testing/bdd/test_elements_active_times.py
@@ -1,88 +1,149 @@
from ebu_tt_live.documents import EBUTT3Document
from ebu_tt_live.bindings._ebuttdt import FullClockTimingType
-from pytest_bdd import scenarios, when, then
+from pytest_bdd import scenarios, when, then, parsers
+from pytest import fixture
scenarios('features/timing/elements_active_times.feature')
scenarios('features/timing/elements_active_times_empty_body.feature')
-@when('it has timeBase ')
+@when(parsers.parse('it has timeBase {time_base}'))
def when_time_base(time_base, template_dict):
template_dict['time_base'] = time_base
-@when('it has sequenceIdentifier ')
+@when(parsers.parse('it has sequenceIdentifier {sequence_identifier}'))
def when_seq_id(sequence_identifier, template_dict):
template_dict['sequence_identifier'] = sequence_identifier
-@when('it has sequenceNumber ')
+@when(parsers.parse('it has sequenceNumber {sequence_number}'))
def when_sequence_number(sequence_number, template_dict):
template_dict['sequence_number'] = sequence_number
-@when('it has body begin time ')
+@fixture
+def body_begin():
+ return None
+
+@when(parsers.parse('it has body begin time {body_begin}'))
+@when(parsers.parse('it has body begin time'))
def when_body_begin(body_begin, template_dict):
template_dict['body_begin'] = body_begin
-@when('it has body duration ')
+@fixture
+def body_dur():
+ return None
+
+@when(parsers.parse('it has body duration {body_dur}'))
+@when(parsers.parse('it has body duration'))
def when_body_dur(body_dur, template_dict):
template_dict['body_dur'] = body_dur
-@when('it has body end time ')
+@fixture
+def body_end():
+ return None
+
+@when(parsers.parse('it has body end time {body_end}'))
+@when(parsers.parse('it has body end time'))
def when_body_end(body_end, template_dict):
template_dict['body_end'] = body_end
-@when('it has div begin time ')
+@fixture
+def div_begin():
+ return None
+
+@when(parsers.parse('it has div begin time {div_begin}'))
+@when(parsers.parse('it has div begin time'))
def when_div_begin(div_begin, template_dict):
template_dict['div_begin'] = div_begin
-@when('it has div end time ')
+@fixture
+def div_end():
+ return None
+
+@when(parsers.parse('it has div end time {div_end}'))
+@when(parsers.parse('it has div end time'))
def when_div_end(div_end, template_dict):
template_dict['div_end'] = div_end
-@when('it has p begin time ')
+@fixture
+def p_begin():
+ return None
+
+@when(parsers.parse('it has p begin time {p_begin}'))
+@when(parsers.parse('it has p begin time'))
def when_p_begin(p_begin, template_dict):
template_dict['p_begin'] = p_begin
-@when('it has p end time ')
+@fixture
+def p_end():
+ return None
+
+@when(parsers.parse('it has p end time {p_end}'))
+@when(parsers.parse('it has p end time'))
def when_p_end(p_end, template_dict):
template_dict['p_end'] = p_end
-@when('it has span1 begin time ')
+@fixture
+def span1_begin():
+ return None
+
+@when(parsers.parse('it has span1 begin time {span1_begin}'))
+@when(parsers.parse('it has span1 begin time'))
def when_span1_begin(span1_begin, template_dict):
template_dict['span1_begin'] = span1_begin
-@when('it has span1 end time ')
+@fixture
+def span1_end():
+ return None
+
+@when(parsers.parse('it has span1 end time {span1_end}'))
+@when(parsers.parse('it has span1 end time'))
def when_span1_end(span1_end, template_dict):
template_dict['span1_end'] = span1_end
-@when('it has span2 begin time ')
+@fixture
+def span2_begin():
+ return None
+
+@when(parsers.parse('it has span2 begin time {span2_begin}'))
+@when(parsers.parse('it has span2 begin time'))
def when_span2_begin(span2_begin, template_dict):
template_dict['span2_begin'] = span2_begin
-@when('it has span2 end time ')
+@fixture
+def span2_end():
+ return None
+
+@when(parsers.parse('it has span2 end time {span2_end}'))
+@when(parsers.parse('it has span2 end time'))
def when_span2_end(span2_end, template_dict):
template_dict['span2_end'] = span2_end
-@when('it is available at ')
+@fixture
+def availability_time():
+ return None
+
+@when(parsers.parse('it is available at {availability_time}'))
+@when(parsers.parse('it is available at'))
def when_doc_available(test_context, availability_time):
if availability_time:
test_context['document'].availability_time = FullClockTimingType(availability_time).timedelta
-@then('body active begin time is ')
+@then(parsers.parse('body active begin time is {body_active_begin}'))
def then_body_active_begin(test_context, body_active_begin):
computed_begin = test_context['document'].binding.body.computed_begin_time
if body_active_begin == "undefined":
@@ -92,7 +153,7 @@ def then_body_active_begin(test_context, body_active_begin):
assert body_active_begin_timedelta == computed_begin
-@then('body active end time is ')
+@then(parsers.parse('body active end time is {body_active_end}'))
def then_body_active_end(test_context, body_active_end):
computed_end = test_context['document'].binding.body.computed_end_time
if body_active_end == "undefined":
@@ -102,7 +163,7 @@ def then_body_active_end(test_context, body_active_end):
assert body_active_end_timedelta == computed_end
-@then('div active begin time is ')
+@then(parsers.parse('div active begin time is {div_active_begin}'))
def then_div_active_begin(test_context, div_active_begin):
computed_begin = test_context['document'].binding.body.orderedContent()[0].value.computed_begin_time
@@ -113,7 +174,7 @@ def then_div_active_begin(test_context, div_active_begin):
assert div_active_begin_timedelta == computed_begin
-@then('div active end time is ')
+@then(parsers.parse('div active end time is {div_active_end}'))
def then_div_active_end(test_context, div_active_end):
computed_end = test_context['document'].binding.body.orderedContent()[0].value.computed_end_time
if div_active_end == "undefined":
@@ -123,7 +184,7 @@ def then_div_active_end(test_context, div_active_end):
assert div_active_end_timedelta == computed_end
-@then('p active begin time is ')
+@then(parsers.parse('p active begin time is {p_active_begin}'))
def then_p_active_begin(test_context, p_active_begin):
computed_begin = test_context['document'].binding.body.orderedContent()[0].value.orderedContent()[0].value.computed_begin_time
if p_active_begin == "undefined":
@@ -133,7 +194,7 @@ def then_p_active_begin(test_context, p_active_begin):
assert p_active_begin_timedelta == computed_begin
-@then('p active end time is ')
+@then(parsers.parse('p active end time is {p_active_end}'))
def then_p_active_end(test_context, p_active_end):
computed_end = test_context['document'].binding.body.orderedContent()[0].value.orderedContent()[0].value.computed_end_time
if p_active_end == "undefined":
@@ -143,7 +204,7 @@ def then_p_active_end(test_context, p_active_end):
assert p_active_end_timedelta == computed_end
-@then('span1 active begin time is ')
+@then(parsers.parse('span1 active begin time is {span1_active_begin}'))
def then_span1_active_begin(test_context, span1_active_begin):
computed_begin = test_context['document'].binding.body.orderedContent()[0].value.orderedContent()[0].value.orderedContent()[1].value.computed_begin_time
if span1_active_begin == "undefined":
@@ -153,7 +214,7 @@ def then_span1_active_begin(test_context, span1_active_begin):
assert span1_active_begin_timedelta == computed_begin
-@then('span1 active end time is ')
+@then(parsers.parse('span1 active end time is {span1_active_end}'))
def then_span1_active_end(test_context, span1_active_end):
computed_end = test_context['document'].binding.body.orderedContent()[0].value.orderedContent()[0].value.orderedContent()[1].value.computed_end_time
if span1_active_end == "undefined":
@@ -163,7 +224,7 @@ def then_span1_active_end(test_context, span1_active_end):
assert span1_active_end_timedelta == computed_end
-@then('span2 active begin time is ')
+@then(parsers.parse('span2 active begin time is {span2_active_begin}'))
def then_span2_active_begin(test_context, span2_active_begin):
computed_begin = test_context['document'].binding.body.orderedContent()[0].value.orderedContent()[0].value.orderedContent()[3].value.computed_begin_time
if span2_active_begin == "undefined":
@@ -173,7 +234,7 @@ def then_span2_active_begin(test_context, span2_active_begin):
assert span2_active_begin_timedelta == computed_begin
-@then('span2 active end time is ')
+@then(parsers.parse('span2 active end time is {span2_active_end}'))
def then_span2_active_end(test_context, span2_active_end):
computed_end = test_context['document'].binding.body.orderedContent()[0].value.orderedContent()[0].value.orderedContent()[3].value.computed_end_time
if span2_active_end == "undefined":
diff --git a/testing/bdd/test_facet.py b/testing/bdd/test_facet.py
index df3e81876..e65025fd9 100644
--- a/testing/bdd/test_facet.py
+++ b/testing/bdd/test_facet.py
@@ -1,10 +1,11 @@
-from pytest_bdd import when, scenarios
+from pytest_bdd import when, scenarios, parsers
+from pytest import fixture
scenarios('features/validation/facet.feature')
-@when('it has facet1 applied to element ')
+@when(parsers.parse('it has facet1 applied to element {parent1}'))
def when_facet1_to_parent1(parent1, template_dict, test_context):
test_context['parent1'] = parent1
key = parent1 + "_facets"
@@ -14,20 +15,20 @@ def when_facet1_to_parent1(parent1, template_dict, test_context):
template_dict[key] = "')
+@when(parsers.parse('facet1 has attribute {link1}'))
def when_facet1_link1(link1, template_dict, test_context):
key = test_context['parent1'] + "_facets"
if link1:
template_dict[key] += ' link="{}"'.format(link1)
-@when('facet1 contains string ')
+@when(parsers.parse('facet1 contains string {term1}'))
def when_facet1_term1(term1, template_dict, test_context):
key = test_context['parent1'] + "_facets"
template_dict[key] += '>{}'.format(term1)
-@when('it has facet2 applied to element ')
+@when(parsers.parse('it has facet2 applied to element {parent2}'))
def when_facet2_to_parent2(parent2, template_dict, test_context):
test_context['parent2'] = parent2
key = parent2 + "_facets"
@@ -37,20 +38,25 @@ def when_facet2_to_parent2(parent2, template_dict, test_context):
template_dict[key] = "')
+@when(parsers.parse('facet2 has attribute {link2}'))
def when_facet2_link2(link2, template_dict, test_context):
key = test_context['parent2'] + "_facets"
if link2:
template_dict[key] += ' link="{}"'.format(link2)
-@when('facet2 contains string ')
+@when(parsers.parse('facet2 contains string {term2}'))
def when_facet2_term2(term2, template_dict, test_context):
key = test_context['parent2'] + "_facets"
template_dict[key] += '>{}'.format(term2)
-@when('it has element facet1 with attribute ')
+@fixture
+def expresses1():
+ return None
+
+@when(parsers.parse('it has element facet1 with attribute {expresses1}'))
+@when(parsers.parse('it has element facet1 with attribute'))
def when_facet1_expresses1(expresses1, template_dict):
value = '')
+@fixture
+def expresses2():
+ return None
+
+@when(parsers.parse('it has element facet2 with attribute {expresses2}'))
+@when(parsers.parse('it has element facet2 with attribute'))
def when_facet2_expresses2(expresses2, template_dict):
value = '')
+@fixture
+def expresses3():
+ return None
+
+@when(parsers.parse('it has element facet3 with attribute {expresses3}'))
+@when(parsers.parse('it has element facet3 with attribute'))
def when_facet3_expresses3(expresses3, template_dict):
value = '')
+@when(parsers.parse('documentFacet has atribute {summary}'))
def when_documentFacet_summary(summary, template_dict):
template_dict['document_facets'] = 'test_facet'.format(summary)
diff --git a/testing/bdd/test_handover.py b/testing/bdd/test_handover.py
index c583a1fb3..a0417df1e 100644
--- a/testing/bdd/test_handover.py
+++ b/testing/bdd/test_handover.py
@@ -1,6 +1,7 @@
+from _pytest.fixtures import fixture
import pytest
-from pytest_bdd import scenarios, given, when, then
+from pytest_bdd import scenarios, given, when, then, parsers
from ebu_tt_live.node import handover as handover_node
from ebu_tt_live.documents import EBUTT3Document
from ebu_tt_live.carriage.interface import IProducerCarriage
@@ -11,7 +12,7 @@
scenarios('features/handover/handover.feature')
-@given('a handover node with and ')
+@given(parsers.parse('a handover node with {authors_group_identifier} and {sequence_identifier}'), target_fixture='given_handover_node')
def given_handover_node(authors_group_identifier, sequence_identifier):
carriage = MagicMock(spec=IProducerCarriage)
carriage.expects.return_value = EBUTT3Document
@@ -24,65 +25,75 @@ def given_handover_node(authors_group_identifier, sequence_identifier):
return instance
-@when('it has and ')
+@when(parsers.parse('it has sequence id {sequence_identifier1} and sequence num {sequence_number1}'))
def when_sequence_id_and_num_1(sequence_identifier1, sequence_number1, template_dict):
template_dict['sequence_identifier'] = sequence_identifier1
template_dict['sequence_number'] = sequence_number1
-@when('it has and ')
+@when(parsers.parse('new document has sequence id {sequence_identifier2} and sequence num {sequence_number2}'))
def when_sequence_id_and_num_2(sequence_identifier2, sequence_number2, template_dict):
template_dict['sequence_identifier'] = sequence_identifier2
template_dict['sequence_number'] = sequence_number2
-@when('it has ')
+@when(parsers.parse('it has {authors_group_identifier}'))
def when_authors_group_id(template_dict, authors_group_identifier):
template_dict['authors_group_identifier'] = authors_group_identifier
-@when('it has ')
+@pytest.fixture
+def authors_group_identifier1():
+ return None
+
+@when(parsers.parse('it has authors group identifier {authors_group_identifier1}'))
+@when(parsers.parse('it has authors group identifier'))
def when_authors_group_id1(template_dict, authors_group_identifier1):
template_dict['authors_group_identifier'] = authors_group_identifier1
-@when('it has ')
+@when(parsers.parse('new document has authors group identifier {authors_group_identifier2}'))
def when_authors_group_id1(template_dict, authors_group_identifier2):
template_dict['authors_group_identifier'] = authors_group_identifier2
-@when('it has ')
+@fixture
+def authors_group_control_token1():
+ return None
+
+@when(parsers.parse('it has authors group control token {authors_group_control_token1}'))
+@when(parsers.parse('it has authors group control token'))
def when_authors_group_token1(template_dict, authors_group_control_token1):
template_dict['authors_group_control_token'] = authors_group_control_token1
-@when('it has ')
+@when(parsers.parse('new document has authors group control token {authors_group_control_token2}'))
def when_authors_group_token2(template_dict, authors_group_control_token2):
template_dict['authors_group_control_token'] = authors_group_control_token2
-@when('new document is created')
+@when(parsers.parse('new document is created'))
def new_doc_created(template_dict):
template_dict.clear()
-@when('handover node processes document')
+@when(parsers.parse('handover node processes document'))
def new_document(test_context, given_handover_node):
given_handover_node.process_document(test_context['document'])
-@then('handover node emits documents')
+@then(parsers.parse('handover node emits {emitted_documents} documents'))
def then_handover_node_emits(given_handover_node, emitted_documents):
assert given_handover_node.producer_carriage.emit_data.call_count == int(emitted_documents)
-@then('handover node errors when processing document')
+@then(parsers.parse('handover node errors when processing document'))
def then_handover_node_errors(given_handover_node, test_context):
with pytest.raises(Exception):
given_handover_node.process_document(test_context['document'])
-@then('the emitted documents belong to and use consecutive sequence numbering from 1')
+@then(parsers.parse('the emitted documents belong to {sequence_identifier} and use consecutive sequence numbering from 1'))
def then_handover_node_produces_sequence(given_handover_node, sequence_identifier):
counter = 1
for pos_args, kw_args in given_handover_node.producer_carriage.emit_data.call_args_list:
@@ -91,14 +102,19 @@ def then_handover_node_produces_sequence(given_handover_node, sequence_identifie
counter += 1
-@then('the emitted documents have and they specify a token')
+@then(parsers.parse('the emitted documents have {authors_group_identifier} and they specify a token'))
def then_handover_parameter_passthrough(given_handover_node, authors_group_identifier):
for pos_args, kw_args in given_handover_node.producer_carriage.emit_data.call_args_list:
assert kw_args['data'].authors_group_identifier == authors_group_identifier
assert kw_args['data'].authors_group_control_token is not None
-@then('the emitted documents have ')
+@pytest.fixture
+def authors_group_selected_sequence_identifiers():
+ return ''
+
+@then(parsers.parse('the emitted documents have {authors_group_selected_sequence_identifiers}'))
+@then(parsers.parse('the emitted documents have'))
def then_authors_group_selected_sequence_id(given_handover_node, authors_group_selected_sequence_identifiers):
# NOTE: The comma is a valid sequenceIdentifier character but we use it as a divisor in the test. Make sure
# the tests use sequence identifiers without commas.
diff --git a/testing/bdd/test_padding_data_type.py b/testing/bdd/test_padding_data_type.py
index 069439479..3d78b0063 100644
--- a/testing/bdd/test_padding_data_type.py
+++ b/testing/bdd/test_padding_data_type.py
@@ -1,10 +1,11 @@
-from pytest_bdd import when, scenarios
+from pytest_bdd import when, scenarios, parsers
+from pytest import fixture
scenarios('features/validation/padding_data_type.feature')
-@when(' has a padding attribute')
+@when(parsers.parse('{tag} has a padding attribute'))
def when_tag_has_padding(tag, template_dict):
if tag == "tt:style":
template_dict["style_padding"] = 'tts:padding="1px"'
@@ -16,26 +17,46 @@ def when_tag_has_padding(tag, template_dict):
template_dict["span_padding"] = 'tts:padding="1px"'
-@when('it has a padding attribute')
+@when(parsers.parse('it has a padding attribute'))
def when_padding_attribute(template_dict):
template_dict["test_padding_syntax"] = True
-@when('the padding attribute has ')
+@fixture
+def value1():
+ return ''
+
+@when(parsers.parse('padding attribute component 1 is {value1}'))
+@when(parsers.parse('padding attribute component 1 is'))
def when_padding_value1(value1, template_dict):
template_dict["value1"] = value1
-@when('the padding attribute has ')
+@fixture
+def value2():
+ return ''
+
+@when(parsers.parse('padding attribute component 2 is {value2}'))
+@when(parsers.parse('padding attribute component 2 is'))
def when_padding_value2(value2, template_dict):
template_dict["value2"] = value2
-@when('the padding attribute has ')
+@fixture
+def value3():
+ return ''
+
+@when(parsers.parse('padding attribute component 3 is {value3}'))
+@when(parsers.parse('padding attribute component 3 is'))
def when_padding_value3(value3, template_dict):
template_dict["value3"] = value3
-@when('the padding attribute has ')
+@fixture
+def value4():
+ return ''
+
+@when(parsers.parse('padding attribute component 4 is {value4}'))
+@when(parsers.parse('padding attribute component 4 is'))
def when_padding_value4(value4, template_dict):
template_dict["value4"] = value4
diff --git a/testing/bdd/test_passive_node_shall_not_modify_documents.py b/testing/bdd/test_passive_node_shall_not_modify_documents.py
index f26f715a1..1d14ac1c3 100644
--- a/testing/bdd/test_passive_node_shall_not_modify_documents.py
+++ b/testing/bdd/test_passive_node_shall_not_modify_documents.py
@@ -11,7 +11,7 @@
scenarios('features/nodes/passive_nodes_shall_not_modify_document.feature')
-@given('a distributing node')
+@given('a distributing node', target_fixture='distributing_node')
def distributing_node():
reference_clock = MagicMock()
prod_carriage = MagicMock(spec=IProducerCarriage)
@@ -24,7 +24,7 @@ def distributing_node():
return node
-@given('a buffer delay node')
+@given('a buffer delay node', target_fixture='buffer_delay_node')
def buffer_delay_node():
reference_clock = MagicMock()
prod_carriage = MagicMock(spec=IProducerCarriage)
diff --git a/testing/bdd/test_referenceClockIdentifier.py b/testing/bdd/test_referenceClockIdentifier.py
index d79b2f857..bf8ac627e 100644
--- a/testing/bdd/test_referenceClockIdentifier.py
+++ b/testing/bdd/test_referenceClockIdentifier.py
@@ -1,18 +1,33 @@
-from pytest_bdd import scenarios, when
+from pytest_bdd import scenarios, when, parsers
+from pytest import fixture
scenarios('features/validation/referenceClockIdentifier_constraints.feature')
-@when('it has timeBase ')
+@fixture
+def clock_mode():
+ return None
+
+@when(parsers.parse('it has timeBase {time_base}'))
def when_time_base(time_base, template_dict):
template_dict['time_base'] = time_base
-@when('it has clock mode ')
+@fixture
+def clock_mode():
+ return None
+
+@when(parsers.parse('it has clock mode {clock_mode}'))
+@when(parsers.parse('it has clock mode'))
def when_clock_mode(clock_mode, template_dict):
template_dict['clock_mode'] = clock_mode
-@when('it has reference clock identifier ')
+@fixture
+def ref_clock_id():
+ return None
+
+@when(parsers.parse('it has reference clock identifier {ref_clock_id}'))
+@when(parsers.parse('it has reference clock identifier'))
def when_ref_clock_id(ref_clock_id, template_dict):
template_dict['ref_clock_id'] = ref_clock_id
diff --git a/testing/bdd/test_resolved_times.py b/testing/bdd/test_resolved_times.py
index b8a0ca762..521fda8b7 100644
--- a/testing/bdd/test_resolved_times.py
+++ b/testing/bdd/test_resolved_times.py
@@ -1,6 +1,8 @@
from ebu_tt_live.documents import EBUTT3Document
from ebu_tt_live.bindings._ebuttdt import FullClockTimingType, LimitedClockTimingType
from pytest_bdd import scenarios, then, when, parsers
+from pytest import fixture
+
scenarios('features/timing/resolved_times.feature')
scenarios('features/timing/resolved_times_no_body.feature')
@@ -20,12 +22,12 @@ def when_new_doc(template_dict):
template_dict.clear()
-@when('it has timeBase ')
+@when(parsers.parse('it has timeBase {time_base}'))
def when_time_base(time_base, template_dict):
template_dict['time_base'] = time_base
-@when('it has sequenceIdentifier ')
+@when(parsers.parse('it has sequenceIdentifier {sequence_identifier}'))
def when_seq_id(sequence_identifier, template_dict):
template_dict['sequence_identifier'] = sequence_identifier
@@ -35,67 +37,127 @@ def when_sequence_number(sequence_number, template_dict):
template_dict['sequence_number'] = sequence_number
-@when('it has doc1 body ')
+@fixture
+def doc1_no_body():
+ return None
+
+@when(parsers.parse('it has doc1 body {doc1_no_body}'))
+@when(parsers.parse('it has doc1 body'))
def when_doc1_body(doc1_no_body, template_dict):
template_dict['body'] = doc1_no_body
-@when('it has doc1 body begin time ')
+@fixture
+def doc1_begin():
+ return None
+
+@when(parsers.parse('it has doc1 body begin time {doc1_begin}'))
+@when(parsers.parse('it has doc1 body begin time'))
def when_doc1_body_begin(doc1_begin, template_dict):
template_dict['body_begin'] = doc1_begin
-@when('it has doc1 body end time ')
+@fixture
+def doc1_end():
+ return None
+
+@when(parsers.parse('it has doc1 body end time {doc1_end}'))
+@when(parsers.parse('it has doc1 body end time'))
def when_doc1_body_end(doc1_end, template_dict):
template_dict['body_end'] = doc1_end
-@when('it has doc1 body duration