AS 2.0 Test Suite Approach

I've been giving some thought to how we can design and develop a test
framework for the Activity Streams 2.0 format. Here are some initial
thoughts.

Activity Streams 2.0 is fundamentally about documenting and describing
Activity. To that end, ensuring that implementations are capable of
consistently documenting and describing specific kinds of Activities
is critical. So, an individual test case would take the form of a
Short series of one or more activity statements plus supporting data
that an implementation would be expected to produce in AS2 form. A
second implementation ought to be able to pull in that serialization
and be capable of answering certain specific questions about the
Activities that have occurred.

The following is an example:

Story 1: SWAT0

1. With his phone, Dave takes a photo of Tantek and uploads it using a service
2. Dave tags the photo with Tantek
3. Tantek gets a notification on another service that he's been tagged
in a photo
3. Evan, who is subscribed to Dave, sees the photo on yet another service
4. Evan comments on the photo
5. David and Tantek receive notifications that Evan has commented on the photo

There are six distinct Activities in this story.

A. Dave takes a photo of Tantek
B. Dave adds the photo to a collection
C. Dave tags Tantek in the photo
D. Tantek and Evan are notified about the photo
E. Evan comments on the photo
F. Dave and Tantek are notified about the comment

Ignoring the multiple-platforms aspect of this story, an
implementation describing these activities should produce a set of AS2
Activity statements that accurately describe the story. Assume that
Dave, Tantek and Evan have user identifiers of
"http://dave.example.org", "http://tantek.example.org", and
"http://evan.example.org", respectively.

A. {
  "@context": "http://www.w3.org/ns/activitystreams",
  "@type": "Create",
  "published": "2015-03-31T12:34:56Z",
  "actor": {
    "@type": "Person",
    "@id": "http://dave.example.org",
    "displayName": "Dave"
  },
  "object": {
    "@type": "Image",
    "@id": "http://i.example.org/images/abc.jpg",
    "url": {
      "mediaType": "image/jpeg",
      "href": "http://i.example.org/images/abc.jpg"
    }
  }
}

B. {
  "@context": "http://www.w3.org/ns/activitystreams",
  "@type": "Add",
  "published": "2015-03-31T12:45:56Z",
  "actor": {
    "@type": "Person",
    "@id": "http://dave.example.org",
    "displayName": "Dave",
  },
  "object": {
    "@type": "Image",
    "@id": "http://i.example.org/images/abc.jpg",
    "url": {
      "mediaType": "image/jpeg",
      "href": "http://i.example.org/images/abc.jpg"
    }
  },
  "target": {
    "@type": "Album",
    "@id": "http://i.example.org/images",
    "displayName": "Dave's Photos"
  }
}

C. {
  "@context": "http://www.w3.org/ns/activitystreams",
  "@type": "Add",
  "published": "2015-03-31T12:56:56Z",
  "actor": {
    "@type": "Person",
    "@id": "http://dave.example.org",
    "displayName": "Dave",
  },
  "object": {
    "@type": "Mention",
    "href": "http://tantek.example.org"
  },
  "target": {
    "@type": "Image",
    "@id": "http://i.example.org/images/abc.jpg",
    "url": {
      "mediaType": "image/jpeg",
      "href": "http://i.example.org/images/abc.jpg"
    }
  }
}

D. {
  "@context": "http://www.w3.org/ns/activitystreams",
  "@type": "Announce",
  "published": "2015-03-31T13:34:56Z",
  "actor": {
    "@type": "Person",
    "@id": "http://dave.example.org",
    "displayName": "Dave"
  },
  "object": {
    "@type": "Image",
    "@id": "http://i.example.org/images/abc.jpg",
    "url": {
      "mediaType": "image/jpeg",
      "href": "http://i.example.org/images/abc.jpg"
    },
    "attachment": {
      "@type": "Mention",
      "href": "http://tantek.example.org"
    }
  },
  "to": {
    "@type": "Person",
    "@id": "http://tantek.example.org",
    "displayName": "Tantek"
  },
  "cc": {
    "@type": "Person",
    "@id": "http://evan.example.org",
    "displayName": "Evan"
  }
}

E. {
  "@context": "http://www.w3.org/ns/activitystreams",
  "@type": "Create",
  "published": "2015-03-31T13:45:56Z",
  "actor": {
    "@type": "Person",
    "@id": "http://evan.example.org",
    "displayName": "Evan"
  },
  "object": {
    "@type": "Note",
    "@id": "http://c.example.org/notes/1",
    "content": "What a great photo",
    "inReplyTo": "http://i.example.org/images/abc.jpg"
  }
}

F. {
  "@context": "http://www.w3.org/ns/activitystreams",
  "@type": "Announce",
  "published": "2015-03-31T13:56:56Z",
  "actor": {
    "@type": "Person",
    "@id": "http://evan.example.org",
    "displayName": "Evan"
  },
  "object": {
    "@type": "Note",
    "@id": "http://c.example.org/notes/1",
    "content": "What a great photo",
    "inReplyTo": "http://i.example.org/images/abc.jpg"
  },
  "to": [
    {
      "@type": "Person",
      "@id": "http://tantek.example.org",
      "displayName": "Tantek"
    },
    {
      "@type": "Person",
      "@id": "http://dave.example.org",
      "displayName": "Dave"
    }
  ]
}

Note that there are a number of acceptable variations in the way
implementations can serialize these stories so the test case needs to
take those into consideration. A consuming implementation would need
to be able to answer specific questions about the stories:

1. What did Dave create?
2. Who was tagged in the photo?
3. Who was notified about the photo?
4. Who commented on the photo?
5. What was the text of the comment?
6. Who was notified about the comment?
7. When was the photo created?
8. When was Tantek tagged in the photo?
9. When were Tantek and Evan tagged?

This example case can be improved but it illustrates the point: Given
a set of commonly understood Activity statements, producing
implementations would be expected to produce consistent AS2.0
serializations that consuming implementations would be capable of
consistently handling.

The downside is that this approach can become fairly complicated but
there's really no other way we can do it.

Thoughts?

- James

Received on Tuesday, 31 March 2015 15:15:14 UTC