SlideShare ist ein Scribd-Unternehmen logo
1 von 55
Downloaden Sie, um offline zu lesen
Self-testing REST APIs
with
API First, Swagger and Play
You need two days to write test cases!?
You already have the Requirements Specification.
Just copy and paste from it.
http://inderpsingh.blogspot.de/2010/05/funny-things-that-testers-hear.html
Specification
Specification
Specification
Specification
Architectural style
Specification
Architectural style
Technological stack
Architectural style
Architectural style
REST
REST
• Client-Server
• Stateless
• Cacheable
• Layered System
• Uniform Interface
• Identification of resources
• Manipulation of resources through these representations
• Self-descriptive messages
• Hypermedia as the engine of application state
Everybody's doing it…
Testers, how are you doing it?
All of them are just different views of
the same piece of software…
What is software?
Simple
the programs that run on a computer and perform certain
functions
something used or associated with and usually contrasted
with hardware as the entire set of programs, procedures,
and related documentation associated with a system and
especially a computer system.
Full
Can you remember quality metrics of your current project?
Libraries it uses?
Runtime environment it runs in?
Container or/and hypervisor?
Operating system?
Firmware/BIOS ?
[A] constructive approach to the problem of program
correctness [is] a usual technique to make a program and
then to test it. But, program testing can be a very effective
way to show the presence of bugs, it is hopelessly
inadequate for showing their absence. The only effective
way to raise the confidence level of a program significantly
is to give a convincing proof of its correctness.
-- Edsger, Wybe Di jkstra, ACM Turing Lecture, The Humble Programmer, 1972
Property based testing
Types are specifications of possible values complying to that Type
Types describe the rules that values must comply to
A possibility to generate ranges of data values for given Types
Boolean: True or False
Equality: Equal or Not Equal
Ordering: Greater, Equal or Less
Provable
Numbers
Strings
Pretty much anything not composed from Provables
Falsifiable
Let’s look again at our system
aka Ports and Adapters
Chris Fidao
https://www.youtube.com/watch?v=6SBjKOwVq0o
Specification
Architectural style
Technology stack
Let’s look again at our solution space
Transport
Transport
Validations
Validations
Model
Model
DRY
DRY
Most people take DRY to mean you shouldn't duplicate code.
That's not its intention. The idea behind DRY is far grander
than that. DRY says that every piece of system knowledge
should have one authoritative, unambiguous representation.
Dave Thomas
Specification is software
It should be a single source of
truth about the system
Formal specification gives us:
Possibility to prove implementation conformance
Self-Evident poorly specified areas
Self-Documented API definition
Intelligent scaffolding
http://www.heppenstall.ca/academics/doc/320/L15_Z.pdf
You need two days to write test cases!?
You already have the requirements specification.
Just copy and paste from it.
Specification
Architectural style
Technology stack
Let’s look again at our technology choice
• Easy to use
• Human readable
• Widest adoption
• Open Source
• Scala and Java
• Dynamic recompilation
• Hot reload
• Asynchronous IO
• Easy to use
Specification
URLs
Verbs
Parameters
Security
Definitions
Specification
URLs
Verbs
Parameters
Security
Definitions Validations
Model
Test Data
Validations
Play Routes
Marshallers
Tests
Controllers
DEMO
Architecture
AST
Play
Akka HTTP
Swagger
RAML
Apiary
Blueprint
…
…
…
Generated code
Metadata
swagger: "2.0"

info:

version: 1.0.0

title: Swagger Petstore

description: A sample API that uses a petstore as an example to
demonstrate features in the swagger-2.0 specification

termsOfService: http://swagger.io/terms/

contact:

name: Swagger API Team

email: foo@example.com

url: http://madskristensen.net

license:

name: MIT

url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT

host: petstore.swagger.io

basePath: /api

schemes:

- http

consumes:

- application/json

produces:

- application/json
Definitions
definitions:

Pet:

allOf:

- $ref: '#/definitions/NewPet'

- required:

- id

properties:

id:

type: integer

format: int64

NewPet:

required:

- name 

properties:

name:

type: string

tag:

type: string 

Error:

required:

- code

- message

properties:

code:

type: integer

format: int32

message:

type: string
object definitions {

trait NewPetDef {

def name: String

def tag: Option[String]

}

case class Pet(

id: Option[Long],

name: String,

tag: Option[String]

) extends NewPetDef

case class NewPet(

name: String,

tag: Option[String]

) extends NewPetDef

case class Error(

code: Int,

message: String

)

}
Test data
definitions:

Pet:

allOf:

- $ref: '#/definitions/NewPet'

- required:

- id

properties:

id:

type: integer

format: int64

NewPet:

required:

- name 

properties:

name:

type: string

tag:

type: string 

Error:

required:

- code

- message

properties:

code:

type: integer

format: int32

message:

type: string
object generatorDefinitions {



def createPet = _generate(PetGenerator)

def createNewPet = _generate(NewPetGenerator)

def createError = _generate(ErrorGenerator)

// test data generator for /definitions/Pet

val PetGenerator =

for {

id <- Gen.option(arbitrary[Long])

name <- arbitrary[String]

tag <- Gen.option(arbitrary[String])

} yield Pet(id, name, tag)

// test data generator for /definitions/NewPet

val NewPetGenerator =

for {

name <- arbitrary[String]

tag <- Gen.option(arbitrary[String])

} yield NewPet(name, tag)

// test data generator for /definitions/Error

val ErrorGenerator =

for {

code <- arbitrary[Int]

message <- arbitrary[String]

} yield Error(code, message)

def _generate[T](gen: Gen[T]) = (count: Int) =>
for (i <- 1 to count) yield gen.sample

}
Validations'#/definitions/NewPet'

red:

rties:

ype: integer

ormat: int64



s:

string

string 

ge

s:

integer

t: int32

:

string
class PetValidation(instance: Pet) {

import de.zalando.play.controllers.PlayValidations._

val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]

val result = {

val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else Right(instance)

}

}





class NewPetValidation(instance: NewPet) {

import de.zalando.play.controllers.PlayValidations._

val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]

val result = {

val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else Right(instance)

}

}





class ErrorValidation(instance: Error) {

import de.zalando.play.controllers.PlayValidations._

val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]

val result = {

val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else Right(instance)

}

}
Validations
/pets/{id}:

get:

description: Returns a user based
on a single ID, if the user does not
have access to the pet

operationId: find pet by id

parameters:

- name: id

in: path

description: ID of pet to fetch

required: true

type: integer

format: int64

responses:

200:

description: pet response

schema:

$ref: '#/definitions/Pet'

default:

description: unexpected error

schema:

$ref: '#/definitions/Error'
class ValidationForPetexpandedYamlfindPetById(in: (Long)) {

val (id) = in



val idConstraints = new ValidationBase[Long] {

override def constraints: Seq[Constraint[Long]] = Seq()

}



val normalValidations =
Seq(idConstraints.applyConstraints(id))



val containerValidations =
Seq.empty[scala.Either[scala.Seq[ParsingError], String]]



val rightResult = Right((id))



val allValidations = normalValidations ++
containerValidations



val result = {

val errors =
allValidations.filter(_.isLeft).flatMap(_.left.get)

if (errors.nonEmpty) Left(errors) else rightResult

}

}
Tests
"discard invalid data" in new WithApplication {

val genInputs =

for {

id <- arbitrary[Long]

} yield (id)

val inputs = genInputs suchThat { i => new ValidationForPetexpandedYamlfindPetById(i).result !=
Right(i) }

val props = forAll(inputs) { i => testInvalidInput(i) }

checkResult(props)

}
Tests
def testInvalidInput(in: (Long)) = {

val (id) = in

val url = s"""/api/pets/${id}"""

val path = route(FakeRequest(GET, url)).get

val validation = new ValidationForPetexpandedYamlfindPetById(id).result

lazy val validations = validation.left.get flatMap {

_.messages map { m => contentAsString(path).contains(m) ?= true }

}

("given an URL: [" + url + "]") |: all(

status(path) ?= BAD_REQUEST,

contentType(path) ?= Some("application/json"),

validation.isLeft ?= true,

all(validations:_*)

)

}
Controllers
private val findPetByIdResponseMimeType = "application/json"

private val findPetByIdActionSuccessStatus = Status(200)



private type findPetByIdActionRequestType = (Long)

private type findPetByIdActionResultType = Pet

private type findPetByIdActionType = findPetByIdActionRequestType => Either[Throwable, findPetByIdActionResultType]



private def errorToStatusfindPetById: PartialFunction[Throwable, Status] = PartialFunction.empty[Throwable, Status]



def findPetByIdAction = (f: findPetByIdActionType) => (id: Long) => Action {

val result = new ValidationForPetexpandedYamlfindPetById(id).result.right.map {

processValidfindPetByIdRequest(f)

}

implicit val marshaller = parsingErrors2Writable(findPetByIdResponseMimeType)

val response = result.left.map { BadRequest(_) }

response.fold(a => a, c => c)

}



private def processValidfindPetByIdRequest(f: findPetByIdActionType)(request: findPetByIdActionRequestType) = {

val callerResult = f(request)

val status = callerResult match {

case Left(error) => (errorToStatusfindPetById orElse defaultErrorMapping)(error)

case Right(result) => findPetByIdActionSuccessStatus

}

implicit val findPetByIdWritableJson = anyToWritable[findPetByIdActionResultType](findPetByIdResponseMimeType)

status(callerResult)

}
Skeletons
class PetexpandedYaml extends PetexpandedYamlBase {



// handler for GET /pets

def findPets = findPetsAction { in : (Option[Seq[String]], Option[Int]) =>

val (tags, limit) = in

???

}



// handler for POST /pets

def addPet = addPetAction { in : (NewPet) =>

val (pet) = in

???

}



// handler for GET /pets/{id}

def findPetById = findPetByIdAction { in : (Long) =>

val (id) = in

???

}



// handler for DELETE /pets/{id}

def deletePet = deletePetAction { in : (Long) =>

val (id) = in

???

}

}
http://github.com/zalando/play-swagger
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Rabble .
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava SchmidtJavaDayUA
 
SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!Taras Oleksyn
 
Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015CiaranMcNulty
 
How to write easy-to-test JavaScript
How to write easy-to-test JavaScriptHow to write easy-to-test JavaScript
How to write easy-to-test JavaScriptYnon Perek
 
Real world dependency injection - DPC10
Real world dependency injection - DPC10Real world dependency injection - DPC10
Real world dependency injection - DPC10Stephan Hochdörfer
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of JavascriptTarek Yehia
 
Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Stephan Hochdörfer
 
Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Andres Almiray
 
Finding the Right Testing Tool for the Job
Finding the Right Testing Tool for the JobFinding the Right Testing Tool for the Job
Finding the Right Testing Tool for the JobCiaranMcNulty
 
Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Vysakh Sreenivasan
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodeSWIFTotter Solutions
 
Object Oriented PHP - PART-2
Object Oriented PHP - PART-2Object Oriented PHP - PART-2
Object Oriented PHP - PART-2Jalpesh Vasa
 
A Blueprint for Scala Microservices
A Blueprint for Scala MicroservicesA Blueprint for Scala Microservices
A Blueprint for Scala MicroservicesFederico Feroldi
 
Not your father's tests
Not your father's testsNot your father's tests
Not your father's testsSean P. Floyd
 

Was ist angesagt? (19)

Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007Introduction to Active Record at MySQL Conference 2007
Introduction to Active Record at MySQL Conference 2007
 
API first with Swagger and Scala by Slava Schmidt
API first with Swagger and Scala by  Slava SchmidtAPI first with Swagger and Scala by  Slava Schmidt
API first with Swagger and Scala by Slava Schmidt
 
SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!SCULPT! YOUR! TESTS!
SCULPT! YOUR! TESTS!
 
Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015Why Your Test Suite Sucks - PHPCon PL 2015
Why Your Test Suite Sucks - PHPCon PL 2015
 
How to write easy-to-test JavaScript
How to write easy-to-test JavaScriptHow to write easy-to-test JavaScript
How to write easy-to-test JavaScript
 
Crafting [Better] API Clients
Crafting [Better] API ClientsCrafting [Better] API Clients
Crafting [Better] API Clients
 
Real world dependency injection - DPC10
Real world dependency injection - DPC10Real world dependency injection - DPC10
Real world dependency injection - DPC10
 
TDD, BDD, RSpec
TDD, BDD, RSpecTDD, BDD, RSpec
TDD, BDD, RSpec
 
Art of Javascript
Art of JavascriptArt of Javascript
Art of Javascript
 
Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11Testing untestable code - PHPBNL11
Testing untestable code - PHPBNL11
 
KAAccessControl
KAAccessControlKAAccessControl
KAAccessControl
 
Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17Testing Java Code Effectively - BaselOne17
Testing Java Code Effectively - BaselOne17
 
Finding the Right Testing Tool for the Job
Finding the Right Testing Tool for the JobFinding the Right Testing Tool for the Job
Finding the Right Testing Tool for the Job
 
Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)
 
PHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better CodePHP: 4 Design Patterns to Make Better Code
PHP: 4 Design Patterns to Make Better Code
 
Object Oriented PHP - PART-2
Object Oriented PHP - PART-2Object Oriented PHP - PART-2
Object Oriented PHP - PART-2
 
Rails Best Practices
Rails Best PracticesRails Best Practices
Rails Best Practices
 
A Blueprint for Scala Microservices
A Blueprint for Scala MicroservicesA Blueprint for Scala Microservices
A Blueprint for Scala Microservices
 
Not your father's tests
Not your father's testsNot your father's tests
Not your father's tests
 

Andere mochten auch

Super powered API testing
Super powered API testing Super powered API testing
Super powered API testing postmanclient
 
Developing and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST APIDeveloping and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST APIAll Things Open
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101Samantha Geitz
 
SOAP-UI The Web service Testing
SOAP-UI The Web service TestingSOAP-UI The Web service Testing
SOAP-UI The Web service TestingGanesh Mandala
 
4 Major Advantages of API Testing
4 Major Advantages of API Testing4 Major Advantages of API Testing
4 Major Advantages of API TestingQASource
 
OpenStack Tempest and REST API testing
OpenStack Tempest and REST API testingOpenStack Tempest and REST API testing
OpenStack Tempest and REST API testingopenstackindia
 
software testing on whatsapp
software testing on whatsappsoftware testing on whatsapp
software testing on whatsappnil65
 
API Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonAPI Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonTEST Huddle
 
REST API testing with SpecFlow
REST API testing with SpecFlowREST API testing with SpecFlow
REST API testing with SpecFlowAiste Stikliute
 
How to Automate API Testing
How to Automate API TestingHow to Automate API Testing
How to Automate API TestingBruno Pedro
 
Webservices testing using SoapUI
Webservices testing using SoapUIWebservices testing using SoapUI
Webservices testing using SoapUITesting World
 
Testing web services
Testing web servicesTesting web services
Testing web servicesTaras Lytvyn
 

Andere mochten auch (17)

Super powered API testing
Super powered API testing Super powered API testing
Super powered API testing
 
Developing and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST APIDeveloping and Testing a MongoDB and Node.js REST API
Developing and Testing a MongoDB and Node.js REST API
 
REST APIs in Laravel 101
REST APIs in Laravel 101REST APIs in Laravel 101
REST APIs in Laravel 101
 
SOAP-UI The Web service Testing
SOAP-UI The Web service TestingSOAP-UI The Web service Testing
SOAP-UI The Web service Testing
 
Api testing
Api testingApi testing
Api testing
 
4 Major Advantages of API Testing
4 Major Advantages of API Testing4 Major Advantages of API Testing
4 Major Advantages of API Testing
 
OpenStack Tempest and REST API testing
OpenStack Tempest and REST API testingOpenStack Tempest and REST API testing
OpenStack Tempest and REST API testing
 
software testing on whatsapp
software testing on whatsappsoftware testing on whatsapp
software testing on whatsapp
 
API Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj RollisonAPI Testing: The heart of functional testing" with Bj Rollison
API Testing: The heart of functional testing" with Bj Rollison
 
API Testing
API TestingAPI Testing
API Testing
 
Api testing
Api testingApi testing
Api testing
 
REST API testing with SpecFlow
REST API testing with SpecFlowREST API testing with SpecFlow
REST API testing with SpecFlow
 
How to Automate API Testing
How to Automate API TestingHow to Automate API Testing
How to Automate API Testing
 
Pentesting RESTful WebServices v1.0
Pentesting RESTful WebServices v1.0Pentesting RESTful WebServices v1.0
Pentesting RESTful WebServices v1.0
 
Webservices testing using SoapUI
Webservices testing using SoapUIWebservices testing using SoapUI
Webservices testing using SoapUI
 
Pentesting ReST API
Pentesting ReST APIPentesting ReST API
Pentesting ReST API
 
Testing web services
Testing web servicesTesting web services
Testing web services
 

Ähnlich wie QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API First, Swagger and Play"

Whidbey old
Whidbey old Whidbey old
Whidbey old grenaud
 
Measuring Your Code
Measuring Your CodeMeasuring Your Code
Measuring Your CodeNate Abele
 
Measuring Your Code 2.0
Measuring Your Code 2.0Measuring Your Code 2.0
Measuring Your Code 2.0Nate Abele
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Michelangelo van Dam
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Michelangelo van Dam
 
Working Effectively With Legacy Perl Code
Working Effectively With Legacy Perl CodeWorking Effectively With Legacy Perl Code
Working Effectively With Legacy Perl Codeerikmsp
 
Agile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tddAgile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tddSrinivasa GV
 
Developer power tools
Developer power toolsDeveloper power tools
Developer power toolsNick Harrison
 
10 Rules for Safer Code
10 Rules for Safer Code10 Rules for Safer Code
10 Rules for Safer CodeQuang Ngoc
 
Mining Code Examples with Descriptive Text from Software Artifacts
Mining Code Examples with Descriptive Text from Software ArtifactsMining Code Examples with Descriptive Text from Software Artifacts
Mining Code Examples with Descriptive Text from Software ArtifactsPreetha Chatterjee
 
Asp.net MVC - Course 2
Asp.net MVC - Course 2Asp.net MVC - Course 2
Asp.net MVC - Course 2erdemergin
 
Validate your entities with symfony validator and entity validation api
Validate your entities with symfony validator and entity validation apiValidate your entities with symfony validator and entity validation api
Validate your entities with symfony validator and entity validation apiRaffaele Chiocca
 
Secure Programming
Secure ProgrammingSecure Programming
Secure Programmingalpha0
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptdavejohnson
 
Java Programming For Android
Java Programming For AndroidJava Programming For Android
Java Programming For AndroidTechiNerd
 
Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...
Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...
Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...Lionel Briand
 
Extreme
ExtremeExtreme
ExtremeESUG
 

Ähnlich wie QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API First, Swagger and Play" (20)

Whidbey old
Whidbey old Whidbey old
Whidbey old
 
Coding Naked 2023
Coding Naked 2023Coding Naked 2023
Coding Naked 2023
 
Measuring Your Code
Measuring Your CodeMeasuring Your Code
Measuring Your Code
 
Measuring Your Code 2.0
Measuring Your Code 2.0Measuring Your Code 2.0
Measuring Your Code 2.0
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
Working Effectively With Legacy Perl Code
Working Effectively With Legacy Perl CodeWorking Effectively With Legacy Perl Code
Working Effectively With Legacy Perl Code
 
Agile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tddAgile_goa_2013_clean_code_tdd
Agile_goa_2013_clean_code_tdd
 
Developer power tools
Developer power toolsDeveloper power tools
Developer power tools
 
Code review
Code reviewCode review
Code review
 
10 Rules for Safer Code
10 Rules for Safer Code10 Rules for Safer Code
10 Rules for Safer Code
 
Mining Code Examples with Descriptive Text from Software Artifacts
Mining Code Examples with Descriptive Text from Software ArtifactsMining Code Examples with Descriptive Text from Software Artifacts
Mining Code Examples with Descriptive Text from Software Artifacts
 
Asp.net MVC - Course 2
Asp.net MVC - Course 2Asp.net MVC - Course 2
Asp.net MVC - Course 2
 
Validate your entities with symfony validator and entity validation api
Validate your entities with symfony validator and entity validation apiValidate your entities with symfony validator and entity validation api
Validate your entities with symfony validator and entity validation api
 
Secure Programming
Secure ProgrammingSecure Programming
Secure Programming
 
Codeigniter
CodeigniterCodeigniter
Codeigniter
 
Pragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScriptPragmatic Parallels: Java and JavaScript
Pragmatic Parallels: Java and JavaScript
 
Java Programming For Android
Java Programming For AndroidJava Programming For Android
Java Programming For Android
 
Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...
Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...
Mining SQL Injection and Cross Site Scripting Vulnerabilities using Hybrid Pr...
 
Extreme
ExtremeExtreme
Extreme
 

Mehr von GeeksLab Odessa

DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...GeeksLab Odessa
 
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...GeeksLab Odessa
 
DataScience Lab 2017_Блиц-доклад_Турский Виктор
DataScience Lab 2017_Блиц-доклад_Турский ВикторDataScience Lab 2017_Блиц-доклад_Турский Виктор
DataScience Lab 2017_Блиц-доклад_Турский ВикторGeeksLab Odessa
 
DataScience Lab 2017_Обзор методов детекции лиц на изображение
DataScience Lab 2017_Обзор методов детекции лиц на изображениеDataScience Lab 2017_Обзор методов детекции лиц на изображение
DataScience Lab 2017_Обзор методов детекции лиц на изображениеGeeksLab Odessa
 
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...GeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладDataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладGeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладDataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладGeeksLab Odessa
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладDataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладGeeksLab Odessa
 
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...GeeksLab Odessa
 
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...GeeksLab Odessa
 
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко GeeksLab Odessa
 
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...GeeksLab Odessa
 
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...GeeksLab Odessa
 
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...GeeksLab Odessa
 
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...GeeksLab Odessa
 
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...GeeksLab Odessa
 
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...GeeksLab Odessa
 
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот GeeksLab Odessa
 
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...GeeksLab Odessa
 
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js GeeksLab Odessa
 

Mehr von GeeksLab Odessa (20)

DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
DataScience Lab2017_Коррекция геометрических искажений оптических спутниковых...
 
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
DataScience Lab 2017_Kappa Architecture: How to implement a real-time streami...
 
DataScience Lab 2017_Блиц-доклад_Турский Виктор
DataScience Lab 2017_Блиц-доклад_Турский ВикторDataScience Lab 2017_Блиц-доклад_Турский Виктор
DataScience Lab 2017_Блиц-доклад_Турский Виктор
 
DataScience Lab 2017_Обзор методов детекции лиц на изображение
DataScience Lab 2017_Обзор методов детекции лиц на изображениеDataScience Lab 2017_Обзор методов детекции лиц на изображение
DataScience Lab 2017_Обзор методов детекции лиц на изображение
 
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
DataScienceLab2017_Сходство пациентов: вычистка дубликатов и предсказание про...
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладDataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладDataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
 
DataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-докладDataScienceLab2017_Блиц-доклад
DataScienceLab2017_Блиц-доклад
 
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
DataScienceLab2017_Cервинг моделей, построенных на больших данных с помощью A...
 
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
DataScienceLab2017_BioVec: Word2Vec в задачах анализа геномных данных и биоин...
 
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
DataScienceLab2017_Data Sciences и Big Data в Телекоме_Александр Саенко
 
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
DataScienceLab2017_Высокопроизводительные вычислительные возможности для сист...
 
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
DataScience Lab 2017_Мониторинг модных трендов с помощью глубокого обучения и...
 
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
DataScience Lab 2017_Кто здесь? Автоматическая разметка спикеров на телефонны...
 
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
DataScience Lab 2017_From bag of texts to bag of clusters_Терпиль Евгений / П...
 
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
DataScience Lab 2017_Графические вероятностные модели для принятия решений в ...
 
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
DataScienceLab2017_Оптимизация гиперпараметров машинного обучения при помощи ...
 
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
DataScienceLab2017_Как знать всё о покупателях (или почти всё)?_Дарина Перемот
 
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
JS Lab 2017_Mapbox GL: как работают современные интерактивные карты_Владимир ...
 
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
JS Lab2017_Под микроскопом: блеск и нищета микросервисов на node.js
 

Kürzlich hochgeladen

Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 

Kürzlich hochgeladen (20)

Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 

QA Lab: тестирование ПО. Станислав Шмидт: "Self-testing REST APIs with API First, Swagger and Play"

  • 1. Self-testing REST APIs with API First, Swagger and Play
  • 2. You need two days to write test cases!? You already have the Requirements Specification. Just copy and paste from it. http://inderpsingh.blogspot.de/2010/05/funny-things-that-testers-hear.html
  • 10. REST • Client-Server • Stateless • Cacheable • Layered System • Uniform Interface • Identification of resources • Manipulation of resources through these representations • Self-descriptive messages • Hypermedia as the engine of application state
  • 12.
  • 13.
  • 14.
  • 15. Testers, how are you doing it?
  • 16.
  • 17. All of them are just different views of the same piece of software…
  • 19. Simple the programs that run on a computer and perform certain functions
  • 20. something used or associated with and usually contrasted with hardware as the entire set of programs, procedures, and related documentation associated with a system and especially a computer system. Full
  • 21. Can you remember quality metrics of your current project? Libraries it uses? Runtime environment it runs in? Container or/and hypervisor? Operating system? Firmware/BIOS ?
  • 22. [A] constructive approach to the problem of program correctness [is] a usual technique to make a program and then to test it. But, program testing can be a very effective way to show the presence of bugs, it is hopelessly inadequate for showing their absence. The only effective way to raise the confidence level of a program significantly is to give a convincing proof of its correctness. -- Edsger, Wybe Di jkstra, ACM Turing Lecture, The Humble Programmer, 1972
  • 24. Types are specifications of possible values complying to that Type Types describe the rules that values must comply to A possibility to generate ranges of data values for given Types
  • 25. Boolean: True or False Equality: Equal or Not Equal Ordering: Greater, Equal or Less Provable
  • 26. Numbers Strings Pretty much anything not composed from Provables Falsifiable
  • 27. Let’s look again at our system
  • 28.
  • 29. aka Ports and Adapters Chris Fidao https://www.youtube.com/watch?v=6SBjKOwVq0o
  • 32. DRY
  • 33. DRY Most people take DRY to mean you shouldn't duplicate code. That's not its intention. The idea behind DRY is far grander than that. DRY says that every piece of system knowledge should have one authoritative, unambiguous representation. Dave Thomas
  • 34. Specification is software It should be a single source of truth about the system
  • 35. Formal specification gives us: Possibility to prove implementation conformance Self-Evident poorly specified areas Self-Documented API definition Intelligent scaffolding http://www.heppenstall.ca/academics/doc/320/L15_Z.pdf
  • 36. You need two days to write test cases!? You already have the requirements specification. Just copy and paste from it.
  • 37. Specification Architectural style Technology stack Let’s look again at our technology choice
  • 38. • Easy to use • Human readable • Widest adoption • Open Source • Scala and Java • Dynamic recompilation • Hot reload • Asynchronous IO • Easy to use
  • 41. DEMO
  • 45. Metadata swagger: "2.0"
 info:
 version: 1.0.0
 title: Swagger Petstore
 description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
 termsOfService: http://swagger.io/terms/
 contact:
 name: Swagger API Team
 email: foo@example.com
 url: http://madskristensen.net
 license:
 name: MIT
 url: http://github.com/gruntjs/grunt/blob/master/LICENSE-MIT
 host: petstore.swagger.io
 basePath: /api
 schemes:
 - http
 consumes:
 - application/json
 produces:
 - application/json
  • 46. Definitions definitions:
 Pet:
 allOf:
 - $ref: '#/definitions/NewPet'
 - required:
 - id
 properties:
 id:
 type: integer
 format: int64
 NewPet:
 required:
 - name 
 properties:
 name:
 type: string
 tag:
 type: string 
 Error:
 required:
 - code
 - message
 properties:
 code:
 type: integer
 format: int32
 message:
 type: string object definitions {
 trait NewPetDef {
 def name: String
 def tag: Option[String]
 }
 case class Pet(
 id: Option[Long],
 name: String,
 tag: Option[String]
 ) extends NewPetDef
 case class NewPet(
 name: String,
 tag: Option[String]
 ) extends NewPetDef
 case class Error(
 code: Int,
 message: String
 )
 }
  • 47. Test data definitions:
 Pet:
 allOf:
 - $ref: '#/definitions/NewPet'
 - required:
 - id
 properties:
 id:
 type: integer
 format: int64
 NewPet:
 required:
 - name 
 properties:
 name:
 type: string
 tag:
 type: string 
 Error:
 required:
 - code
 - message
 properties:
 code:
 type: integer
 format: int32
 message:
 type: string object generatorDefinitions {
 
 def createPet = _generate(PetGenerator)
 def createNewPet = _generate(NewPetGenerator)
 def createError = _generate(ErrorGenerator)
 // test data generator for /definitions/Pet
 val PetGenerator =
 for {
 id <- Gen.option(arbitrary[Long])
 name <- arbitrary[String]
 tag <- Gen.option(arbitrary[String])
 } yield Pet(id, name, tag)
 // test data generator for /definitions/NewPet
 val NewPetGenerator =
 for {
 name <- arbitrary[String]
 tag <- Gen.option(arbitrary[String])
 } yield NewPet(name, tag)
 // test data generator for /definitions/Error
 val ErrorGenerator =
 for {
 code <- arbitrary[Int]
 message <- arbitrary[String]
 } yield Error(code, message)
 def _generate[T](gen: Gen[T]) = (count: Int) => for (i <- 1 to count) yield gen.sample
 }
  • 48. Validations'#/definitions/NewPet'
 red:
 rties:
 ype: integer
 ormat: int64
 
 s:
 string
 string 
 ge
 s:
 integer
 t: int32
 :
 string class PetValidation(instance: Pet) {
 import de.zalando.play.controllers.PlayValidations._
 val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else Right(instance)
 }
 }
 
 
 class NewPetValidation(instance: NewPet) {
 import de.zalando.play.controllers.PlayValidations._
 val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else Right(instance)
 }
 }
 
 
 class ErrorValidation(instance: Error) {
 import de.zalando.play.controllers.PlayValidations._
 val allValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else Right(instance)
 }
 }
  • 49. Validations /pets/{id}:
 get:
 description: Returns a user based on a single ID, if the user does not have access to the pet
 operationId: find pet by id
 parameters:
 - name: id
 in: path
 description: ID of pet to fetch
 required: true
 type: integer
 format: int64
 responses:
 200:
 description: pet response
 schema:
 $ref: '#/definitions/Pet'
 default:
 description: unexpected error
 schema:
 $ref: '#/definitions/Error' class ValidationForPetexpandedYamlfindPetById(in: (Long)) {
 val (id) = in
 
 val idConstraints = new ValidationBase[Long] {
 override def constraints: Seq[Constraint[Long]] = Seq()
 }
 
 val normalValidations = Seq(idConstraints.applyConstraints(id))
 
 val containerValidations = Seq.empty[scala.Either[scala.Seq[ParsingError], String]]
 
 val rightResult = Right((id))
 
 val allValidations = normalValidations ++ containerValidations
 
 val result = {
 val errors = allValidations.filter(_.isLeft).flatMap(_.left.get)
 if (errors.nonEmpty) Left(errors) else rightResult
 }
 }
  • 50. Tests "discard invalid data" in new WithApplication {
 val genInputs =
 for {
 id <- arbitrary[Long]
 } yield (id)
 val inputs = genInputs suchThat { i => new ValidationForPetexpandedYamlfindPetById(i).result != Right(i) }
 val props = forAll(inputs) { i => testInvalidInput(i) }
 checkResult(props)
 }
  • 51. Tests def testInvalidInput(in: (Long)) = {
 val (id) = in
 val url = s"""/api/pets/${id}"""
 val path = route(FakeRequest(GET, url)).get
 val validation = new ValidationForPetexpandedYamlfindPetById(id).result
 lazy val validations = validation.left.get flatMap {
 _.messages map { m => contentAsString(path).contains(m) ?= true }
 }
 ("given an URL: [" + url + "]") |: all(
 status(path) ?= BAD_REQUEST,
 contentType(path) ?= Some("application/json"),
 validation.isLeft ?= true,
 all(validations:_*)
 )
 }
  • 52. Controllers private val findPetByIdResponseMimeType = "application/json"
 private val findPetByIdActionSuccessStatus = Status(200)
 
 private type findPetByIdActionRequestType = (Long)
 private type findPetByIdActionResultType = Pet
 private type findPetByIdActionType = findPetByIdActionRequestType => Either[Throwable, findPetByIdActionResultType]
 
 private def errorToStatusfindPetById: PartialFunction[Throwable, Status] = PartialFunction.empty[Throwable, Status]
 
 def findPetByIdAction = (f: findPetByIdActionType) => (id: Long) => Action {
 val result = new ValidationForPetexpandedYamlfindPetById(id).result.right.map {
 processValidfindPetByIdRequest(f)
 }
 implicit val marshaller = parsingErrors2Writable(findPetByIdResponseMimeType)
 val response = result.left.map { BadRequest(_) }
 response.fold(a => a, c => c)
 }
 
 private def processValidfindPetByIdRequest(f: findPetByIdActionType)(request: findPetByIdActionRequestType) = {
 val callerResult = f(request)
 val status = callerResult match {
 case Left(error) => (errorToStatusfindPetById orElse defaultErrorMapping)(error)
 case Right(result) => findPetByIdActionSuccessStatus
 }
 implicit val findPetByIdWritableJson = anyToWritable[findPetByIdActionResultType](findPetByIdResponseMimeType)
 status(callerResult)
 }
  • 53. Skeletons class PetexpandedYaml extends PetexpandedYamlBase {
 
 // handler for GET /pets
 def findPets = findPetsAction { in : (Option[Seq[String]], Option[Int]) =>
 val (tags, limit) = in
 ???
 }
 
 // handler for POST /pets
 def addPet = addPetAction { in : (NewPet) =>
 val (pet) = in
 ???
 }
 
 // handler for GET /pets/{id}
 def findPetById = findPetByIdAction { in : (Long) =>
 val (id) = in
 ???
 }
 
 // handler for DELETE /pets/{id}
 def deletePet = deletePetAction { in : (Long) =>
 val (id) = in
 ???
 }
 }