SlideShare a Scribd company logo
Specification by Examples
for Symfony2 applications
About me
Cofounder
Cofounder
on Github
on Twitter
- PHP & Cloud @ Genova - 24 Oct
- Internet Of Things! @ Turin [CFP] - 15 Nov
- CloudComputing @ Turin [CFP ASAP]
Corley S.r.l. - @CorleyCloud
UpCloo LTD - @UpCloo
wdalmut
walterdalmut
www.cloudparty.it
internetof.it
www.cloudconf.it
Repo with all examples
Repo on github
Software delivery
customer wants A
project manager understand B
developers write down C
developers effectively write down D
customer realize to get E
Successive refinements of E
E'
E''
E'''
E''''
E'''''
The customer will never obtain an A
The problem is to achieve a
single communication domain
How many points does it have?
Example from: Bridging the communication gap (Gojko Adzic)
10
5
14
9
Effectively, there is no right
answer.
It depends on what you consider as a point
Behaviour-driven development
is a software development process based on test-driven development
(TDD). Behavior-driven development combines the general techniques
and principles of TDD with ideas from domain-driven design and object-
oriented analysis and design to provide software development and
management teams with shared tools and a shared process to
collaborate on software development.
from wikipedia
BDD
Although BDD is principally an idea about how software development
should be managed by both business interests and technical insight
from wikipedia
Dan North: What is a story?
Behaviour-driven development is an “outside-in” methodology. It starts
at the outside by identifying business outcomes, and then drills down
into the feature set that will achieve those outcomes. Each feature is
captured as a “story”, which defines the scope of the feature along with
its acceptance criteria. This article introduces the BDD approach to
defining and identifying stories and their acceptance criteria.
Read the article here
BDD is more than tools, but we
are here in order to use BDD
methodology in our Symfony2
projects
Tools
Behat - Behaviour-driven framework
Mink - Web Acceptance testing framework
Pay attention on Behat version
The latest is 3.0 (at today) but there are so many examples and
docs for 2.5
We will work with 3.0
Here is a story
Feature: a description of this feature
        Scenario: A business situation
            Given a precondition
            And another precondition
            When an actor execute an action
            And another action appends
            Then some testable result is in place
            And another condition should be verified
        Scenario: Another business scenario starts
Here is a story in Italian
Funzionalità: una generica descrizione di questa funzionalità
        Scenario: una situazione di business
            Data una precondizione
            E ancora una nuova precondizione
            Quando un attore esegue una azione
            E succede anche un altra azione
            Allora esite un risultato testabile
            Ed un nuova condizione da verificare
        Scenario: Un altro scenario di business da verificare
Gherkin is a Business Readable
and Domain Specific Language
that let us describe software’s
behaviour without detailing
how that behaviour is
implemented.
From the cucumber project
Gherkin supports so many
languages
We are building a common language with
different actors involved into to design
process
There are at least two ways to use behat in
your Symfony2 applications
Per-bundle features
Specific features per bundle
Application features
All features in a single folder
Personally prefer a single place for all
features
Mainly because it is so difficult to share the
application bundle strategies to a
customer
Keep the focus on the communication not
how we implement the solution
behat.yml
default:
    suites:
        default:
            path: %paths.base%/features
            contexts: [BehatMinkExtensionContextMinkContext]
    extensions:
        BehatSymfony2Extension: ~
        BehatMinkExtension:
            base_url: http://localhost:8000
            sessions:
                default:
                    symfony2: ~
Behat uses a "FeatureContext"
as a clue for join the Gherkin
language with the application
A feature
Feature: An hello world feature example
    Scenario: Just say hello to me!
        When I am on "/hello/walter"
        Then I should see "Hello Walter"
Every step is a custom method in the
FeatureContext
/** @Given /^I am on "([^"]*)"$/ */
public function goOnPage($url)
{
...
}
Mink carries different predefined steps
I am on "a page"
I press "Get me in!"
I should see "Ok, you are in"
and more... (CSS selectors etc.)
But remember that we are building a
common communication domain
Write down a new step that use a mink's steps instead force a new
definition of something
By Examples
Scenario Outline: Just say hello to everyone!
    When I am on <page>
    Then I should see <hello>
    Examples:
        | page              | hello            |
        | "/hello/walter"   | "Hello Walter"   |
        | "/hello/marco"    | "Hello Marco"    |
        | "/hello/giovanni" | "Hello Giovanni" |
        | "/hello/martina"  | "Hello Martina"  |
Expectations
Scenario Outline: Say a better hello to special guests
    When I am on <page>
    Then I should see <hello>
    Examples:
        | page              | hello                   |
        | "/hello/fabien"   | "Captain on the bridge" |
        | "/hello/walter"   | "Hello Walter"          |
        | "/hello/marco"    | "Hello Marco"           |
        | "/hello/giovanni" | "Hello Giovanni"        |
        | "/hello/martina"  | "Hello Martina"         |
If we run it
Feature: An hello world feature example
Scenario Outline: Say a better hello to special guests
    When I am on <page>
    Then I should see <hello>
    Examples:
    | page              | hello                   |
    | "/hello/fabien"   | "Captain on the bridge" |
        The text "Captain on the bridge" was not found
        anywhere in the text of the current page. (BehatMinkExceptionResponseTextException)
    | "/hello/walter"   | "Hello Walter"          |
    | "/hello/marco"    | "Hello Marco"           |
    | "/hello/giovanni" | "Hello Giovanni"        |
    | "/hello/martina"  | "Hello Martina"         |
‐‐‐ Failed scenarios:
    features/hello.feature:24
Fix the code
class DefaultController extends Controller
{
    public function indexAction($name)
    {
        if ($name == "fabien") {
            $name = "Captain on the bridge";
        }
        return $this‐>render('CorleyBaseBundle:Default:index.html.twig', array('name' => $name));
    }
}
My steps interacts with the entity manager
default:
    suites:
        default:
            path: %paths.base%/features
            contexts:
                ‐ BehatMinkExtensionContextMinkContext
                ‐ HelloFeatureContext:
                    entityManager: '@doctrine.orm.entity_manager'
    extensions:
        BehatSymfony2Extension: ~
        BehatMinkExtension:
            base_url: http://localhost:8000
            sessions:
                default:
                    symfony2: ~
Create contexts
bin/behat ‐‐init
Context constructor
/**
 * Behat context class.
 */
class HelloFeatureContext implements SnippetAcceptingContext
{
    private $entityManager;
    /**
     * Initializes context.
     *
     * Every scenario gets its own context object.
     * You can also pass arbitrary arguments to the context constructor through behat.yml.
     */
    public function __construct(EntityManager $entityManager)
    {
        $this‐>entityManager = $entityManager;
    }
                        
My context clears all before runs
/**
 * @BeforeScenario
 */
public function clearDatabase()
{
    $purger = new ORMPurger($this‐>entityManager);
    $purger‐>purge();
}
Load books for this scenario
Feature: My books features
    Scenario: List my books
        Given there are books
            | title                          | author          |
            | Specification by Examples      | Gojko Adzic     |
            | Bridging the communication gap | Gojko Adzic     |
            | The RSpec Book                 | David Chelimsky |
        When I am on "/books"
        Then I should see "Specification by Examples"
        And I should see "Bridging the communication gap"
        And I should see "The RSpec Book"
Run it!
(and get the missing step definition)
‐‐‐ HelloFeatureContext has missing steps. Define them with these snippets:
    /**
    * @Given there are books
    */
    public function thereAreBooks(TableNode $table)
    {
        throw new PendingException();
    }
My custom step
/**
 * @Given there are books
 */
public function thereAreBooks(TableNode $table)
{
    foreach ($table‐>getHash() as $row) {
        $book = new Book();
        $book‐>setTitle($row["title"]);
        $book‐>setAuthor($row["author"]);
        $this‐>entityManager‐>persist($book);
    }
    $this‐>entityManager‐>flush();
}
Scenarios can share the same background
Feature: My books features
    Background:
        Given there are books
            | title                          | author          |
            | Specification by Examples      | Gojko Adzic     |
            | Bridging the communication gap | Gojko Adzic     |
            | The RSpec Book                 | David Chelimsky |
    Scenario: List my books
        When I am on "/books"
        Then I should see "Specification by Examples"
        And I should see "Bridging the communication gap"
        And I should see "The RSpec Book"
A story
Scenario: An interested user becomes an active user
    Given an interested user with email "walter.dalmut@gmail.com"
    When he goes to homepage
    And he fills all personal fields
    Then he confirms the registration
    And he should be registered as an unconfirmed user
    And he should receive the registration email
    And he should be in the reserved area
Signup Feature Context
class SignupContext implements SnippetAcceptingContext, MinkAwareContext
    {
        private $mink;
        private $minkParameters;
        private $entityManager;
    ...
        public function setMink(Mink $mink)
        {
            $this‐>mink = $mink;
        }
        public function setMinkParameters(array $parameters)
        {
            $this‐>minkParameters = $parameters;
        }
    ...
GIVEN i am an interested user with email
/**
 * @Given I am an interested user with email :arg1
 */
public function anInterestedUserWithEmail($email)
{
    // shared in the feature context
    $this‐>email = $email;
    // Check that is an interested user and not an existing one
    Assert::assertNull(
        $this‐>entityManager
            ‐>getRepository("CorleyBaseBundle:User")‐>findOneByEmail($email)
    );
}
WHEN i fill all personal fields
/**
 * @When I fill all personal fields
 */
public function heFillsAllPersonalFields()
{
    $this‐>mink‐>getSession()‐>getPage()
        ‐>find("css", "#corley_bundle_basebundle_user_email")
        ‐>setValue($this‐>email);
    $this‐>mink‐>getSession()‐>getPage()
        ‐>find("css", "#corley_bundle_basebundle_user_name")
        ‐>setValue(rand(0,100000));
}
THEN I confirm my registration
/**
 * @Then I confirm my registration
 */
public function iConfirmTheRegistration()
{
    $client = $this‐>mink
        ‐>getSession()
        ‐>getDriver()
        ‐>getClient();
    $client‐>followRedirects(false);
    $this‐>mink‐>getSession()‐>getPage()
        ‐>find("css", "#corley_bundle_basebundle_user_submit")‐>click();
}
THEN I should be registered as an
unconfirmed user
/**
 * @Then I should be registered as an unconfirmed user
 */
public function heShouldBeRegisteredAsAnUnconfirmedUser()
{
    $this‐>entityManager‐>clear();
    $entity = $this‐>entityManager
        ‐>getRepository("CorleyBaseBundle:User")
        ‐>findOneByEmail($this‐>email);
    Assert::assertNotNull($entity);
    Assert::assertFalse($entity‐>isConfirmed());
}
THEN I should receive the reg. email
/**
 * @Then I should receive the registration email
 */
public function heShouldReceiveTheRegistrationEmail()
{
    $driver = $this‐>mink‐>getSession()‐>getDriver();
    if (!$driver instanceof KernelDriver) {
        throw new RuntimeException("Only kernel drivers");
    }
    $profile = $driver‐>getClient()‐>getProfile();
    if (false === $profile) {
        throw new RuntimeException("Profiler is disabled");
    }
    $collector = $profile‐>getCollector('swiftmailer');
    Assert::assertCount(1, $collector‐>getMessages());
}
You can wrap a "getProfiler" in a separate method
THEN I should be in the reserved area
/**
 * @Then I should be in the reserved area
 */
public function heShouldBeInTheReservedArea()
{
    $client = $this‐>mink
        ‐>getSession()
        ‐>getDriver()
        ‐>getClient();
    $client‐>followRedirects(true);
    $client‐>followRedirect();
    $this‐>mink‐>assertSession()‐>pageTextContains("Hello reserved area!");
}
You can wrap the redirection in seperate, reusable steps
There are so many features in Behat
But, remember that the goal is to bridging the communication gap
between actors of the same project with different backgrounds
Do not use it for functional testing
(use LiipFunctionalTestBundle for that or anything else)
Thanks for listening
Any question?

More Related Content

What's hot (20)

PPTX
GitHub Actions for 5 minutes
Svetlin Nakov
 
PPTX
Ultimate Productivity Tools
Amal Dev
 
PPTX
Enjector Kernel - Workflow Module Demo
Ajay Soni
 
ODP
Ci for-android-apps
Anthony Dahanne
 
PPT
Visual studio 11 developer preview
Wei Sun
 
PPT
Python with dot net and vs2010
Wei Sun
 
PDF
Eclipse RCP outside of Eclipse IDE - Gradle to the rescue!
Michał Ćmil
 
PPTX
Fullstack workshop
Assaf Gannon
 
PDF
Wuff: Building Eclipse Applications and Plugins with Gradle
Andrey Hihlovsky
 
PDF
High Productivity Web Development Workflow
Vũ Nguyễn
 
PPTX
Continuous integration and delivery and deployment
Rubén Sospedra
 
PDF
Workshop - Golang language
Vincent Composieux
 
PDF
KKBOX WWDC17 Xcode IDE - Hardy
Liyao Chen
 
PPTX
CloudExpo 2018: Docker - Power Your Move to the Cloud
Elton Stoneman
 
PDF
Exploring the GitHub Service Universe
Björn Kimminich
 
PDF
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
VMware Tanzu
 
PPT
Eclipse 2011 Hot Topics
Lars Vogel
 
PPTX
Continuous Integration of Mobile Apps with Docker and Appium
Emergya
 
PPTX
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
OdessaJS Conf
 
PDF
Appium Dockerization: from Scratch to Advanced Implementation - HUSTEF 2019
Sargis Sargsyan
 
GitHub Actions for 5 minutes
Svetlin Nakov
 
Ultimate Productivity Tools
Amal Dev
 
Enjector Kernel - Workflow Module Demo
Ajay Soni
 
Ci for-android-apps
Anthony Dahanne
 
Visual studio 11 developer preview
Wei Sun
 
Python with dot net and vs2010
Wei Sun
 
Eclipse RCP outside of Eclipse IDE - Gradle to the rescue!
Michał Ćmil
 
Fullstack workshop
Assaf Gannon
 
Wuff: Building Eclipse Applications and Plugins with Gradle
Andrey Hihlovsky
 
High Productivity Web Development Workflow
Vũ Nguyễn
 
Continuous integration and delivery and deployment
Rubén Sospedra
 
Workshop - Golang language
Vincent Composieux
 
KKBOX WWDC17 Xcode IDE - Hardy
Liyao Chen
 
CloudExpo 2018: Docker - Power Your Move to the Cloud
Elton Stoneman
 
Exploring the GitHub Service Universe
Björn Kimminich
 
Continuous Delivery for Microservice Architectures with Concourse & Cloud Fou...
VMware Tanzu
 
Eclipse 2011 Hot Topics
Lars Vogel
 
Continuous Integration of Mobile Apps with Docker and Appium
Emergya
 
Олексій Гончар "Використання Electron в розробці корпоративної відео-мессeндж...
OdessaJS Conf
 
Appium Dockerization: from Scratch to Advanced Implementation - HUSTEF 2019
Sargis Sargsyan
 

Similar to Symfony2 Specification by examples (20)

PPTX
BDD in my team: how we do it
Darius Kasperavicius
 
PDF
Phpers day 2019
Dariusz Drobisz
 
PDF
Behavioral driven development with Behat
Promet Source
 
ODP
BDD with Behat
Richard Shank
 
PDF
Behavior driven development with Behat and Gherkin
marcusamoore
 
PPTX
Behavior-Driven Development (BDD) in context
Alexander Kress
 
KEY
BDD with Behat and Symfony2
katalisha
 
PDF
PHP CE 2018 - Building Symfony application with Ports and Adapters approach a...
Dariusz Drobisz
 
PDF
Bridging the gap between business and technology - Behaviour Driven Developme...
marcin_pajdzik
 
PDF
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
Ryan Weaver
 
PDF
BDD in Action – principles, practices and real-world application
John Ferguson Smart Limited
 
PPTX
A step-by-step guide to behavior-driven development
valuebound
 
ODP
Behaviour Driven Development
Carsten Nielsen
 
PDF
DDD with Behat
Anton Serdyuk
 
PDF
Behat internals for advanced usage. Symfony Camp 2016
Sergey Polischook
 
PDF
Expo qa from user stories to automated acceptance tests with bdd
Eduardo Riol
 
PDF
Behat - Drupal Yorkshire
Nathan Lisgo
 
PDF
Behavioural Driven Development in Zf2
David Contavalli
 
PPT
BDD communication bridges - Expedia TED talk
Aliaksandr Ikhelis
 
PDF
BDD in PHP - Behat
Łukasz Kużyński
 
BDD in my team: how we do it
Darius Kasperavicius
 
Phpers day 2019
Dariusz Drobisz
 
Behavioral driven development with Behat
Promet Source
 
BDD with Behat
Richard Shank
 
Behavior driven development with Behat and Gherkin
marcusamoore
 
Behavior-Driven Development (BDD) in context
Alexander Kress
 
BDD with Behat and Symfony2
katalisha
 
PHP CE 2018 - Building Symfony application with Ports and Adapters approach a...
Dariusz Drobisz
 
Bridging the gap between business and technology - Behaviour Driven Developme...
marcin_pajdzik
 
Grand Rapids PHP Meetup: Behavioral Driven Development with Behat
Ryan Weaver
 
BDD in Action – principles, practices and real-world application
John Ferguson Smart Limited
 
A step-by-step guide to behavior-driven development
valuebound
 
Behaviour Driven Development
Carsten Nielsen
 
DDD with Behat
Anton Serdyuk
 
Behat internals for advanced usage. Symfony Camp 2016
Sergey Polischook
 
Expo qa from user stories to automated acceptance tests with bdd
Eduardo Riol
 
Behat - Drupal Yorkshire
Nathan Lisgo
 
Behavioural Driven Development in Zf2
David Contavalli
 
BDD communication bridges - Expedia TED talk
Aliaksandr Ikhelis
 
BDD in PHP - Behat
Łukasz Kużyński
 
Ad

More from Corley S.r.l. (20)

PDF
Aws rekognition - riconoscimento facciale
Corley S.r.l.
 
PDF
AWSome day 2018 - scalability and cost optimization with container services
Corley S.r.l.
 
PDF
AWSome day 2018 - API serverless with aws
Corley S.r.l.
 
PDF
AWSome day 2018 - database in cloud
Corley S.r.l.
 
PDF
Trace your micro-services oriented application with Zipkin and OpenTracing
Corley S.r.l.
 
PDF
Apiconf - The perfect REST solution
Corley S.r.l.
 
PDF
Apiconf - Doc Driven Development
Corley S.r.l.
 
PDF
Authentication and authorization in res tful infrastructures
Corley S.r.l.
 
PDF
Flexibility and scalability of costs in serverless infrastructures
Corley S.r.l.
 
PDF
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
Corley S.r.l.
 
PDF
React vs Angular2
Corley S.r.l.
 
PDF
A single language for backend and frontend from AngularJS to cloud with Clau...
Corley S.r.l.
 
PPTX
AngularJS: Service, factory & provider
Corley S.r.l.
 
PPTX
The advantage of developing with TypeScript
Corley S.r.l.
 
PDF
Angular coding: from project management to web and mobile deploy
Corley S.r.l.
 
PDF
Corley cloud angular in cloud
Corley S.r.l.
 
PDF
Measure your app internals with InfluxDB and Symfony2
Corley S.r.l.
 
PDF
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Corley S.r.l.
 
PDF
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Corley S.r.l.
 
PDF
Middleware PHP - A simple micro-framework
Corley S.r.l.
 
Aws rekognition - riconoscimento facciale
Corley S.r.l.
 
AWSome day 2018 - scalability and cost optimization with container services
Corley S.r.l.
 
AWSome day 2018 - API serverless with aws
Corley S.r.l.
 
AWSome day 2018 - database in cloud
Corley S.r.l.
 
Trace your micro-services oriented application with Zipkin and OpenTracing
Corley S.r.l.
 
Apiconf - The perfect REST solution
Corley S.r.l.
 
Apiconf - Doc Driven Development
Corley S.r.l.
 
Authentication and authorization in res tful infrastructures
Corley S.r.l.
 
Flexibility and scalability of costs in serverless infrastructures
Corley S.r.l.
 
CloudConf2017 - Deploy, Scale & Coordinate a microservice oriented application
Corley S.r.l.
 
React vs Angular2
Corley S.r.l.
 
A single language for backend and frontend from AngularJS to cloud with Clau...
Corley S.r.l.
 
AngularJS: Service, factory & provider
Corley S.r.l.
 
The advantage of developing with TypeScript
Corley S.r.l.
 
Angular coding: from project management to web and mobile deploy
Corley S.r.l.
 
Corley cloud angular in cloud
Corley S.r.l.
 
Measure your app internals with InfluxDB and Symfony2
Corley S.r.l.
 
Read Twitter Stream and Tweet back pictures with Raspberry Pi & AWS Lambda
Corley S.r.l.
 
Deploy and Scale your PHP App with AWS ElasticBeanstalk and Docker- PHPTour L...
Corley S.r.l.
 
Middleware PHP - A simple micro-framework
Corley S.r.l.
 
Ad

Recently uploaded (20)

PPTX
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
PDF
Alpha Altcoin Setup : TIA - 19th July 2025
CIFDAQ
 
PDF
UiPath on Tour London Community Booth Deck
UiPathCommunity
 
PDF
Trading Volume Explained by CIFDAQ- Secret Of Market Trends
CIFDAQ
 
PDF
Integrating IIoT with SCADA in Oil & Gas A Technical Perspective.pdf
Rejig Digital
 
PDF
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
PDF
Ampere Offers Energy-Efficient Future For AI And Cloud
ShapeBlue
 
PPTX
Building and Operating a Private Cloud with CloudStack and LINBIT CloudStack ...
ShapeBlue
 
PPTX
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
PDF
Building Resilience with Digital Twins : Lessons from Korea
SANGHEE SHIN
 
PPTX
Lecture 5 - Agentic AI and model context protocol.pptx
Dr. LAM Yat-fai (林日辉)
 
PDF
Market Insight : ETH Dominance Returns
CIFDAQ
 
PDF
UiPath vs Other Automation Tools Meeting Presentation.pdf
Tracy Dixon
 
PDF
Generative AI in Healthcare: Benefits, Use Cases & Challenges
Lily Clark
 
PDF
Novus-Safe Pro: Brochure-What is Novus Safe Pro?.pdf
Novus Hi-Tech
 
PPTX
python advanced data structure dictionary with examples python advanced data ...
sprasanna11
 
PDF
OpenInfra ID 2025 - Are Containers Dying? Rethinking Isolation with MicroVMs.pdf
Muhammad Yuga Nugraha
 
PPTX
Building a Production-Ready Barts Health Secure Data Environment Tooling, Acc...
Barts Health
 
PDF
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
PPTX
Simplifying End-to-End Apache CloudStack Deployment with a Web-Based Automati...
ShapeBlue
 
AI Code Generation Risks (Ramkumar Dilli, CIO, Myridius)
Priyanka Aash
 
Alpha Altcoin Setup : TIA - 19th July 2025
CIFDAQ
 
UiPath on Tour London Community Booth Deck
UiPathCommunity
 
Trading Volume Explained by CIFDAQ- Secret Of Market Trends
CIFDAQ
 
Integrating IIoT with SCADA in Oil & Gas A Technical Perspective.pdf
Rejig Digital
 
State-Dependent Conformal Perception Bounds for Neuro-Symbolic Verification
Ivan Ruchkin
 
Ampere Offers Energy-Efficient Future For AI And Cloud
ShapeBlue
 
Building and Operating a Private Cloud with CloudStack and LINBIT CloudStack ...
ShapeBlue
 
AVL ( audio, visuals or led ), technology.
Rajeshwri Panchal
 
Building Resilience with Digital Twins : Lessons from Korea
SANGHEE SHIN
 
Lecture 5 - Agentic AI and model context protocol.pptx
Dr. LAM Yat-fai (林日辉)
 
Market Insight : ETH Dominance Returns
CIFDAQ
 
UiPath vs Other Automation Tools Meeting Presentation.pdf
Tracy Dixon
 
Generative AI in Healthcare: Benefits, Use Cases & Challenges
Lily Clark
 
Novus-Safe Pro: Brochure-What is Novus Safe Pro?.pdf
Novus Hi-Tech
 
python advanced data structure dictionary with examples python advanced data ...
sprasanna11
 
OpenInfra ID 2025 - Are Containers Dying? Rethinking Isolation with MicroVMs.pdf
Muhammad Yuga Nugraha
 
Building a Production-Ready Barts Health Secure Data Environment Tooling, Acc...
Barts Health
 
NewMind AI Weekly Chronicles – July’25, Week III
NewMind AI
 
Simplifying End-to-End Apache CloudStack Deployment with a Web-Based Automati...
ShapeBlue
 

Symfony2 Specification by examples