lundi 29 octobre 2012

Test the Web Forward

During 2 days (26 and 27 of October, 2012), Test The Web Forward was held in Paris where people come from different countries mostlty France and US (San Fransisco) but even Australia to write test for the latest W3C specifications (HTML5, CSS3, Apache Cordova, etc.).

Vincent Hardy (Adobe) introduced the event and welcomed the attendee.
Then came Robin Berjon (W3C) to talk about how to read a spect in a way to write a test for it: read it forward and backward!
Spec have to deal with complex things (ex. the red button implementation may differs in details from one browser to another: form, shape)
In the spec look for the conformance requirement for details
  • The "product" what it is applied to (ex. uers agrnt, the browser) -> what you want to test (product)
  • Strinctness level (must, should: option, may)
  • Prerequisites
  • Behabiour of the product (e.g. ignore the element)
  • Defined terms: tell you what is it mean (e.g. absent, empty string, ignore)
Finding definitins (repeated) are close to the begining

Then, Rebecca Hauck (Adobe) talked about reference tests (reftest) and how to write one.
Then, James Graham (Opera) talked about how to use testharness.js to writing javascript tests for W3C specifications. Here is some examples from the talk:
  • Sync test: example with local storage getItem() that returns the value associated with a key, or null if none
  • Async test: clear storage example when clearStorage() called from a window than an event is fired in an iframe contained in the same document
Finally, Elika J. Etemad also known with fantasai (Mozilla) How to file a good bug report in bugzilla or any other bug reporting system.

After this session, lightning talks started where experts presented some W3C specifications they would like people to join to write test for them. The goal is tests inheritance as they can be writting befroe code as test were writting for W3C spec.

Apache Cordova (Michael Brooks from Adobe)
Apache Cordova (also known as PhoneGap) implements W3C API to map javascript code to native methods. The task was to convert jasmine test it to testharness.js (they were around 200 tests).

IndexedDB (Odin Hørthe Omdal from Opera)
Under active development, Implemented in many browsers, needs tests (333 so far).

CSS3 backgrounds (Microsoft)

W3C HTML5 Testing Task Force
A groud writting tests for testing HMTL5 spec, has a CVS.
Why? used by user agent implementers (tv, stereo, , refrigirator).
Read wiki and presentation.

WebRTC aim is to be able to do video/audio communication on the web + P2P communication between two browser.
  • GetUserMedia: allows a script to get access to microphone, first ask user consent.
  • PeerConnection: helps you send video data over internet to : quality of video based on available for the browser.
  • DataChannel: send banch of data between browsers.
More resources can be found here:

jeudi 4 octobre 2012

Read/Write NFC tag in Android

Android & NFC howto

When a NFC tag is discovered, the system checks if the foreground application has registered to such an Intent with a call to enableForegroundDispatch(). If not, it checks whether any other applications has registered for the NDEF_DISCOVERED intent. If an application want to register for events related to a tag of a specific technology (e.g. classic MiFare tags) then it should register to the TECH_DISCOVERED intent.
The following diagram explains in details how an event related to reading a tag is handled:

Read NFC tag in Android

Declare in the manifest a specific Activity to receive an Intent when a NFC tag is read by the device:
<activity android:name=".NfcReaderActivity" android:label="NfcReaderActivity">
    <intent-filter>
     <action android:name="android.nfc.action.TAG_DISCOVERED"/>
     <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

To register the foreground Activity for tag reading events, add following lines to onResume() method:
@Override
protected onResume() {
  PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
  mAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
} 

In the onNewIntent(Intent)to read the tag after receiving a ACTION_TAG_DISCOVERED intent :
protected void onNewIntent(Intent intent) {
  String action = intent.getAction();
  if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)){
    Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    NdefMessage[] messages;
    if (rawMsgs != null) {
      messages = new NdefMessage[rawMsgs.length];
      for (int i = 0; i < rawMsgs.length; i++) {
        messages[i] = (NdefMessage) rawMsgs[i];     
        // To get a NdefRecord and its different properties from a NdefMesssage   
     NdefRecord record = messages[i].getRecords()[i];
     byte[] id = record.getId();
     short tnf = record.getTnf();
     byte[] type = record.getType();
     String message = getTextData(record.getPayload());
      }
    }
  }
}

This is how to read the content tag of type text RTD_TEXT
// Decoding a payload containing text
private String getTextData(byte[] payload) {
  if(payload == null) 
    return null;
  try {
    String encoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
    int langageCodeLength = payload[0] & 0077;
    return new String(payload, langageCodeLength + 1, payload.length - langageCodeLength - 1, encoding);     
  } catch(Exception e) {
    e.printStackTrace();
  }
  return null;
}

Write NFC tag in Android

In the manifest:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
in onCreate() get the NfcAdapter:
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
The data part of a TAG is a NdefMessage of multiple NdefRecord this is how to encode a text into a payload:
// Encoding a text into a tag payload 
NdefRecord createRecord(String message) {
  byte[] langBytes = Locale.ENGLISH.getLanguage().getBytes(Charset.forName("US-ASCII"));
  byte[] textBytes = message.getBytes(Charset.forName("UTF-8"));
  char status = (char) (langBytes.length);
  byte[] data = new byte[1 + langBytes.length + textBytes.length];
  data[0] = (byte) status;
  System.arraycopy(langBytes, 0, data, 1, langBytes.length);
  System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
  return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
}
// Create a message from a record
NdefMessage createMessage(NdefRecord record) {
  NdefRecord[] records = new NdefRecord[1];
  records[0] = record;
  NdefMessage message = new NdefMessage(records);
  return message;
}
To enable/disable sending a message each time a tag is read
@Override
protected void onPause() {
  super.onPause();
  nfcAdapter.disableForegroundNdefPush(this);
}
@Override
protected void onResume() {
  super.onResume();
  NdefRecord record = creerRecord("this is a message");
  NdefMessage message = creerMessage(record);
  nfcAdapter.enableForegroundNdefPush(this, message);
}
If there is no tag, we can simulate a tag been read by sending the corresponding intent, this is how:
final Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED);
NdefMessage[] messages = new NdefMessage[1];
messages[0] = createMessage(createRecord("Simulating a tag reception"));
intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, messages);
startActivity(intent); 

Reference Programming Android, chapter 16: Sensors, NFC, Speech, Gestures, and Accessibility.