Given a list of test records (from parsed JSON), this returns one row per test-attribute combination, with a stable set of columns.
.build_test_attributes_long(records)data.frame with columns:
testId
attributeTypeId
attributeTypeName
attributeValueId
attributeValueName
list of test records (each may contain $attributes)
Only attributes with at least one non-blank field are included. Tests with no attributes (or only blank attributes) do not appear in the result.