42
EMBEDDED SOFTWARE DEVELOPMENT USING BDD Itamar Hassin September 2014

Embedded software development using BDD

Embed Size (px)

DESCRIPTION

This presentation makes the case for BDD in general and focuses on its use within embedded software development. Using the Cucumber gem, I will demonstrate how to use feature files in the context of working with embedded hardware projects, and explain how to extend the framework using the Wire protocol to allow integration tests to run in-situ, which greatly enhances testing coverage compared to PC-based testing using emulators. I also cover the notion of a SpecFlow gateway, with which one can achieve end-to-end testing with a variety of devices as an orchestration mechanism for broader tests.

Citation preview

Page 1: Embedded software development using BDD

EMBEDDED SOFTWARE DEVELOPMENT USING BDD

Itamar Hassin September 2014

Page 2: Embedded software development using BDD

THIS TALK COVERS

•Embedded development challenges !

•The case for BDD !

•Simulating the target !

•Accessing the target remotely/in-situ !

•Orchestrating access to multiple targets

Page 3: Embedded software development using BDD

EMBEDDED DEVELOPMENT CHALLENGES

•A simulator rarely available or not fully functional !

•Remote device verification !

•Complex state-machines !

•Test coverage often limited to unit testing

Page 4: Embedded software development using BDD

THE CASE FOR CUCUMBER

•Direct mapping from user story acceptance criteria

!

•Living documentation, unified view of the product !

•Helps defines ‘done’: Code is tested and validated !

•BDD promotes lean code & emergent design !

•Authored by the team: BAs/QA/Devs

Page 5: Embedded software development using BDD

CLOSER TO THE SOURCE

Page 6: Embedded software development using BDD

PREMISE FOR AUTOMATIONProgramatically validate that code solves the problem by articulating behaviour in machine-readable form.

Page 7: Embedded software development using BDD

CUCUMBER FOR EMBEDDED!

Page 8: Embedded software development using BDD

WRITE ONCE, USE THRICE

Feature: Alarm assured to appear in quiet mode !Scenario: Pressure alarm Given device is in quiet mode When pressure sensor is disconnected Then a silent alarm will appear

Page 9: Embedded software development using BDD

IMPLEMENT STEPS

Given(/Given device is in quiet mode $/) do @device.set_quiet_mode(1) end

Page 10: Embedded software development using BDD

IMPLEMENT A SIMULATOR

class Device def set_quiet_mode(flag) if (flag) mode |= QUIET_MODE else mode &= ~QUIET_MODE end update_driver(mode) end end

Page 11: Embedded software development using BDD

VALIDATE UNDER SIMULATOR

Scenario: Pressure alarm Given device is in quiet mode When pressure sensor is disconnected Then a silent alarm will appear !

5 scenarios (5 passed) 26 steps (26 passed) 0m0.052s

Page 12: Embedded software development using BDD

WHEN SIMULATION IS NOT ENOUGH

Page 13: Embedded software development using BDD

THE “WIRE”

•When your system does not have native support

•When you want a lean, portable implementation

Page 14: Embedded software development using BDD

SIMPLIFIED WIRE PROTOCOL

Page 15: Embedded software development using BDD

WIRE IMPLEMENTATION BLUEPRINT

•TCP/IP loop managing Cucumber protocol

•Function table for API invocation

•API implementation returning status to Cucumber

Page 16: Embedded software development using BDD

HOOKING CUCUMBER TO LISTENER

features/step_definitions/cucumber.wire host: deviceport: 3901

Page 17: Embedded software development using BDD

LISTENER TCP/IP LOOP

while(fgets(buff, sizeof(buff), rStream)) { respond_to_cucumber(wStream, buff); }

Page 18: Embedded software development using BDD

WIRE HANDLERvoid respond_to_cucumber(FILE* stream, char* msg) { if (MSG_TYPE_IS(msg, "step_matches")) respond_to_step_matches(stream, msg); else if (MSG_TYPE_IS(msg, "invoke")) respond_to_invoke(stream, msg); else if (MSG_TYPE_IS(msg, "begin_scenario")) respond_to_begin(stream, msg); else if (MSG_TYPE_IS(msg, "end_scenario")) respond_to_end(stream, msg); else respond_success(stream); }

Page 19: Embedded software development using BDD

FUNCTION TABLE

stepdef_t stepdefs[] = { { "device is in quiet mode”, set_quiet_mode } };

Page 20: Embedded software development using BDD

INVOKING API FUNCTIONS

void respond_to_invoke(…) { int id = get_function_id(msg); !

stepdefs[id].callback(arg_val) ? failure(stream) : success(stream); }

Page 21: Embedded software development using BDD

TARGET API

int set_quiet_mode(const char *arg) { context->requested_mode = atoi(arg); context->quiet_mode |= context->requested_mode; return(update_driver(context)); }

Page 22: Embedded software development using BDD

IMPLEMENTATION STACK

Page 23: Embedded software development using BDD

WORKING WITH CUCUMBER•Decide on a strategy (off-board, on-board)

•Get appropriate toolchain (cross compiler, linker)

•Implement and port Wire to target

•Run the feature files

•fail/implement/pass/refactor/repeat

Page 24: Embedded software development using BDD

USAGE PATTERNS Off-Board

• Framework on PC • Listener on PC • Proxy API on PC

• Network calls to Target API !

In-Situ • Framework on PC • Listener on Target • API calls on Target

Prog

ress

ion

Page 25: Embedded software development using BDD

WORKING AT A SAFE DISTANCE

Page 26: Embedded software development using BDD

OFF-BOARDCucumber running on

PC

Wire running on PC

Target API running on

PC

Target

NetworkC-implementation

• + Target untouched

• - All API’s must be exposed; low-fidelity; many moving parts;

Page 27: Embedded software development using BDD

UP CLOSE AND PERSONAL

Page 28: Embedded software development using BDD

IN-SITUFramework running on

PC

Cucumber-Wire running

on Target

Network C-implementation

Target API

• + high-fidelity, API’s not exposed

• - Server part of codebase

Page 29: Embedded software development using BDD

COLLABORATIVE ENVIRONMENT

Page 30: Embedded software development using BDD

GATEWAY

!

•Acts as an end-to-end test orchestrator !

•Switchboard events across heterogeneous devices

Page 31: Embedded software development using BDD

COLLABORATIVE END-TO-END TESTING

Framework running on

PC

C-implementation

Cucumber-Wire running

on Target

Targets

NativeWire

Collaboration

Page 32: Embedded software development using BDD

GATEWAY ARCHITECTURE

SpecFlow

Target B

Proxies

A1

B1

Hardware

Serial

Wire

Target ACucumber

Behave

Page 33: Embedded software development using BDD

END-TO-END FEATURES

Feature: Alarm assured to appear in quiet mode !

Scenario: Pressure alarm Given device is in quiet mode When pressure sensor is disconnected Then a silent alarm will appear

Page 34: Embedded software development using BDD

GATEWAY STEPS public class QuietModeSteps { SignalSimulator signalSimulator = new SignalSimulator(); MedicalDevice medicalDevice = new MedicalDevice(“192.168.1.1”, 3901); ! [Given(@"device is quiet mode")] public void GivenDeviceIsQuietMode() { NUnit.Framework.Assert.IsTrue(medicalDevice.SetQuietMode()); } ! [When(@“pressure sensor is disconnected")] public void GivenPressureSensorIsDisconnected() { NUnit.Framework.Assert.IsTrue(signalSimulator.SetPressure(off)); } }

Page 35: Embedded software development using BDD

GATEWAY PROXIES class MedicalDevice { protected Wire wire; ! public MedicalDevice(string ipAddress, int port) { myAddress = ipAddress; wire = new Wire(myAddress, port); wire.Open(); } ! public bool SetQuietMode() { wire.Send("[\"step_matches\",{\"name_to_match\":\"set quiet mode on\"}]\n"); wire.Send("[\"invoke\",{\"id\":\"7\",\"args\":[\"on\"]}]\n"); return(wire.Ack()); } }

Page 36: Embedded software development using BDD

EMULATING WIRE public class Wire { public int Open() { client = new TcpClient(myAddress, myPort); stream = client.GetStream(); return(Send(“[\”begin_scenario\"]\n")); } ! public int Close() { stream = client.GetStream(); Send("[\"end_scenario\"]\n"); return(client.Close()); } }

Page 37: Embedded software development using BDD

SpecFlow

Wire

Proxies

A1

Target

TCP

Given … quiet mode

Wire

int SetQuietMode(“on”) {}

Match: “set quiet\’(on|off)’\”

Invoke: idx:0, params: “on”

SPECFLOW TO WIRE

int set_quiet(char* state){}A

Page 38: Embedded software development using BDD

Exists in proxy? Write wrappers

Exists in Wire?

No

NoYes

Function table entry

Yes

Use in feature/step files

API Exists? No Implement API

Yes

MAINTENANCE CONSIDERATIONS

Page 39: Embedded software development using BDD

•Security - Anyone can connect to Wire!

•Regulation may not allow non-application code on a production system

Shut down the wire thread in production

COMPLIANCE CONSIDERATIONS

Page 40: Embedded software development using BDD

LESSONS LEARNED

Threading

Dual VocabularyThreads & Target Architecture

Page 41: Embedded software development using BDD

REFERENCES•Specification by example

•The Cucumber Book

•Cucumber Recipes

@history_pics/@historyinpicsJim Reese#Wikipedia

National Library of Australia

Photo Credits:

•SpecFlow

Page 42: Embedded software development using BDD

THANK YOU!@itababy

www.in-context.com