Code Monkey home page Code Monkey logo

fastest's Introduction

Fastest - simple parallel testing execution

example branch parameter Latest Stable Version Latest Unstable Version

Only one thing

Execute parallel commands, creating a Process for each Processor (with some goodies for functional tests).

find tests/ -name "*Test.php" | ./vendor/liuggio/fastest/fastest "vendor/phpunit/phpunit/phpunit -c app {};"

Fastest works with any available testing tool! It just executes it in parallel.

It is optimized for functional tests, giving an easy way to work with N databases in parallel.

Motto

"I had a problem,
so I decided to use threads.
tNwoowp rIo bhlaevmes.

Why

We were tired of not being able to run paratest with our project (big complex functional project).
Parallel is a great tool but not so nice for functional tests.
There were no simple tool available for functional tests.

Our old codebase run in 30 minutes, now in 7 minutes with 4 Processors.

Features

  1. Functional tests could use a database per processor using the environment variable.
  2. Tests are randomized by default.
  3. Is not coupled with PhpUnit you could run any command.
  4. Is developed in PHP with no dependencies.
  5. As input you could use a phpunit.xml.dist file or use pipe (see below).
  6. Includes a Behat extension to easily pipe scenarios into fastest.
  7. Increase Verbosity with -v option.
  8. Works with a installation in project or global mode

How

It creates N threads where N is the number of the core in the computer.
Really fast, 100% written in PHP, inspired by Parallel.

Usage

Configure paths to binaries

Examples shown below use paths to binaries installed in the vendor/ directory. You can use symlinks in the bin/ directory by defining the bin-dir parameter of Composer:

composer config "bin-dir" "bin"

Then you'll be able to call binaries in the bin/ directory:

  • bin/fastest instead of vendor/liuggio/fastest/fastest
  • bin/phpunit instead of vendor/phpunit/phpunit/phpunit

Parallelize everything

ls | ./fastest "echo slow operation on {}" -vvv

Using the placeholders

{} is the current test file.
{p} is the current processor number.
{n} is the unique number of the current test. phpunit {} is used as default command.

PHPUnit

A. Using ls, list of folders as input suggested

ls -d test/* | ./vendor/liuggio/fastest/fastest "vendor/phpunit/phpunit/phpunit {};"

B. using find, list of php files as input

find tests/ -name "*Test.php" | ./vendor/liuggio/fastest/fastest  "vendor/phpunit/phpunit/phpunit {};"

C. Using phpunit.xml.dist as input

You can use the option -x and import the test suites from the phpunit.xml.dist

./vendor/liuggio/fastest/fastest -x phpunit.xml.dist "vendor/phpunit/phpunit/phpunit {};"

If you use this option make sure the test-suites contains a lot of directories: this feature should be improved, don't blame help instead.

Functional tests and database

Inside your tests you could use the env. variables,
if you are running tests on a computer that has 4 core, fastest will create 4 threads in parallel, and inside your test you could use those variables to better identify the current process:

echo getenv('ENV_TEST_CHANNEL');          // The number of the current channel that is using the current test eg.2
echo getenv('ENV_TEST_CHANNEL_READABLE'); // Name used to make the database name unique, is a readable name eg. test_2
echo getenv('ENV_TEST_CHANNELS_NUMBER');  // Max channel number on a system (the core number) eg. 4
echo getenv('ENV_TEST_ARGUMENT');         // The current running test eg. tests/UserFunctionalTest.php
echo getenv('ENV_TEST_INC_NUMBER');       // Unique number of the current test eg. 32
echo getenv('ENV_TEST_IS_FIRST_ON_CHANNEL'); // Is 1 if is the first test on its thread useful for clear cache.

Setup the database before

You can also run a script per process before the tests, useful for init schema and fixtures loading.

find tests/ -name "*Test.php" | ./vendor/liuggio/fastest/fastest -b"app/console doc:sch:create -e test" "vendor/phpunit/phpunit/phpunit {};";

Generate and merge code coverage

# Install phpcov in order to merge the code coverage
composer require --dev phpunit/phpcov
# Create a directory where the coverage files will be put
mkdir -p cov/fastest/
# Generate as many files than tests, since {n} is an unique number for each test
find tests/ -name "*Test.php" | vendor/liuggio/fastest/fastest "vendor/phpunit/phpunit/phpunit -c app {} --coverage-php cov/fastest/{n}.cov;"
# Merge the code coverage files
phpcov merge cov/fastest/ --html cov/merge/fastest/

Code coverage will be available in the cov/merge/fastest/ directory.

Storage adapters

If you want to parallel functional tests, and if you have a machine with 4 CPUs, the best thing you could do is create a db foreach parallel process, fastest gives you the opportunity to work easily with Symfony.

Modifying the config_test.yml config file in Symfony, each functional test will look for a database called <database_name>_test_x automatically (x is from 1 to CPUs number).

Doctrine DBAL

config_test.yml

parameters:
    # Stubs
    doctrine.dbal.connection_factory.class: Liuggio\Fastest\Doctrine\DBAL\ConnectionFactory

Doctrine MongoDB Connection

config_test.yml

parameters:
    # Stubs
    doctrine_mongodb.odm.connection.class: Liuggio\Fastest\Doctrine\MongoDB\Connection

SQLite databases

SQLite databases don't have names. It's always 1 database per file. If SQLite driver is detected, instead switching the database name, database path will be changed. To make it work simply add __DBNAME__ placeholder in your database path.

config_test.yml

doctrine:
    dbal:
        driver:   pdo_sqlite
        path:     "%kernel.cache_dir%/__DBNAME__.db"
        
parameters:
    doctrine.dbal.connection_factory.class: Liuggio\Fastest\Doctrine\DBAL\ConnectionFactory

Where __DBNAME__ will be replaced with ENV_TEST_CHANNEL_READABLE value.

Behat.* extension

A Behat extension is included that provides the ability for Behat to output a list of feature files or individual scenarios that would be executed without actually executing them. This list can be piped into fastest to run the scenarios in parallel.

To install the extension just add it to your behat.yml file:

extensions:
    Liuggio\Fastest\Behat\ListFeaturesExtension\Extension: ~

for Behat2:

extensions:
    Liuggio\Fastest\Behat2\ListFeaturesExtension\Extension: ~

After this you will have two additional command line options: --list-features and --list-scenarios. The former will output a list of *.feature files and the later will output each scenario of each feature file, including its line number (e.g. /full/path/Features/myfeature.feature:lineNumber)

This will let you pipe the output directly into fastest to parallelize its execution:

/my/path/behat --list-scenarios | ./vendor/liuggio/fastest/fastest "/my/path/behat {}"

Using --list-scenarios is preferred over --list-features because it will give a more granular scenario-by-scenario output, allowing fastest to shuffle and balance individual tests in a better way.

About browser-based tests (Selenium, Mink, etc)

When a browser is controlled remotely via PHPUnit, Behat or another test suite that is being used by Fastest, the browser makes requests back to the server. The problem is that when the server process the request it has no idea of which fastest channel called it, so there must be a way to set this information before connecting to the database (in order to choose the correct database that corresponds to the channel).

One possible way is to implement the following steps:

1. Set a cookie, GET query parameter or HTTP header with the appropiate channel value

When your test scenario begins, maybe at the authentication phase, set one of the following to the value of the environment variable ENV_TEST_CHANNEL_READABLE:

  • If it's a cookie or a GET query parameter name it ENV_TEST_CHANNEL_READABLE
    • Beware that if you use the GET query parameter option and via automation you click on a link of the browser that doesn't have that query parameter, the request won't have the query parameter the server won't know the channel to initialize.
  • If it's a HTTP header name it X-FASTEST-ENV-TEST-CHANNEL-READABLE and send it on every request to the server.

2. Configure the entry point of your application to set the environment variables for the request

For this is enough to add the following code before booting your application:

\Liuggio\Fastest\Environment\FastestEnvironment::setFromRequest();

This will detect the presence of the ENV_TEST_CHANNEL_READABLE value in any of the contexts mentioned in #1 and set the corresponding environment variable.

For example, in the case of the Symfony framework you may just add it in web/app_dev.php just before require_once __DIR__.'/../app/AppKernel.php':

// ... code
$loader = require_once __DIR__.'/../app/bootstrap.php.cache';
Debug::enable();

\Liuggio\Fastest\Environment\FastestEnvironment::setFromRequest();

require_once __DIR__.'/../app/AppKernel.php';
$kernel = new AppKernel('dev', true);
// ... code

Install

If you use Composer just run composer require --dev 'liuggio/fastest:^1.6'

or simply add a dependency on liuggio/fastest to your project's composer.json file:

{
    "require-dev": {
	    "liuggio/fastest": "^1.6"
    }
}

For a system-wide installation via Composer, you can run:

composer global require "liuggio/fastest=^1.6"

Make sure you have ~/.composer/vendor/bin/ in your path, read more at getcomposer.org

If you want to use it with phpunit you may want to install phpunit/phpunit as dependency.

Run this test with fastest

Usage:
 fastest [-p|--process="..."] [-b|--before="..."] [-x|--xml="..."] [-o|--preserve-order] [--no-errors-summary] [execute]

Arguments:
 execute               Optional command to execute.

Options:
 --process (-p)        Number of parallel processes, default: available CPUs.
 --before (-b)         Execute a process before consuming the queue, it executes this command once per process, useful for init schema and load fixtures.
 --xml (-x)            Read input from a phpunit xml file from the '<testsuites>' collection. Note: it is not used for consuming.
 --preserve-order (-o) Queue is randomized by default, with this option the queue is read preserving the order.
 --rerun-failed (-r)   Re-run failed test with before command if exists.
 --no-errors-summary   Do not display all errors after the test run. Useful with --vv because it already displays errors immediately after they happen.
 --help (-h)           Display this help message.
 --quiet (-q)          Do not output any message.
 --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
 --version (-V)        Display this application version.
 --ansi                Force ANSI output.
 --no-ansi             Disable ANSI output.
 --no-interaction (-n) Do not ask any interactive question.

e.g. ./fastest -x phpunit.xml.dist -v "bin/phpunit {}"

Known problems

If you're faceing problems with unknown command errors, make sure your variables-order php.ini setting contains E. If not, your enviroment variables are not set, and commands that are in your PATH will not work.

Contribution

Please help with code, love, feedback and bug reporting.

Thanks to:

  • @giorrrgio for the mongoDB adapter
  • @diegosainz for the Behat2 adapter
  • you?

License License

Read LICENSE for more information.

fastest's People

Contributors

aitboudad avatar alexislefebvre avatar alexndlm avatar backendtea avatar biederkdo avatar clementgautier avatar diego-sainz-g avatar doncallisto avatar francoispluchino avatar garak avatar gawsoftpl avatar giorrrgio avatar grldk avatar javiereguiluz avatar jdeniau avatar joshuataylor avatar keradus avatar kix avatar liuggio avatar loostro avatar lsimeonov avatar mnocon avatar oskarstark avatar perk11 avatar peter279k avatar peterrehm avatar simpod avatar tarlepp avatar toniperic avatar wcluijt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastest's Issues

Add an unique placeholder

I'm trying to generate code coverage with fastest.

@liuggio suggested to use --log-junit /tmp/logfile{p}.xml, but when I run 26 tests, the value {p} goes from 1 to 4, it looks like the file is overwritten by each test that use the same {p} value.

Currently they are these placeholders:

  • {} is the current test file.
  • {p} is the current processor number.

Can we have another placeholder to ease code coverage logging? I suggest to add another placeholder with an unique number or name, like the ENV_TEST_INC_NUMBER or ENV_TEST_CHANNEL_READABLE variables.

Misleading output "- X shuffled tests into the queue."

See the output when I launch fastest:

$ find src/*/*Bundle/Tests/ -name "*Test.php" | vendor/bin/fastest --process 4 "vendor/bin/phpunit -c app/phpunit.xml.dist {}"
- 26 shuffled tests into the queue.
- Will be consumed by 4 parallel Processes.

26 is the number of files, not the number of tests:

$ find src/*/*Bundle/Tests/ -name "*Test.php" | wc
     26      26    1903

So, X shuffled tests is misleading, it may be X shuffled tests files instead.

[Epic] Request For Contributors - V2.0

The version 1 has been released and it's time to move on,
in this era laptops have 8 cores and the serial commands execution
is a waste of time, when we wrote the lib the processors number were 4 and now are doubled.

On the events branch https://github.com/liuggio/fastest/tree/events (sorry I didn't change the Readme yet) there's a prototype of the new fastest,
it has been totally rewritten with events approach.

The goals:

  • provide a better output decoupled from the processes execution
  • provide a better integration for Phpunit/PhpSpec/Behat and third party service
  • agnostic parallel processing

The future
In the future it could be also a library to help other applications eg. php-cs-fixer or assetic to parallelize processes.

Now

The great benefit of this new approach is the possibility to fetch the data from each process on runtime, and is possible to recreate the same output of any third party.
Is now possible to print on screen with a simple/ugly Subscriber that waits for events with partial content.

Todo:

In this new branch the todo-list is quite big we have to re-add the PhpUnit and Behat adapters, would be great to do it with a deep integration eg. use the PHPUnit php code to read the folder.

  • 1 PHPUnit
    • 1.a InputProducer: Should place the tests into the queue.
    • 1.b PHPUnitOutputSubscriber: handle the output as Phpunit does
    • minor - 1.c Coverage
  • 2 Behat Adaptor
  • 3 porting of the old UI to the new StdOutUISubscriber
  • 4 re-add the MongoDB and Doctrine adapters
  • 5 Better windows support #1, #24

Any suggestions or idea are really welcome...

/cc
@giorrrgio @EmanueleMinotto @perk11 @binarious @GrahamCampbell @dpmancus @aitboudad @diegosainz

False Positives

Not sure if it's fixable, but I think it's important to at least make the issue known.

There is a possibility that running fastest will say a test has passed when it shouldn't. The only cause I have been able to create this issue with is having two classes with the same name but separate namespaces used in a test - e.g. My\First\FileSystem and My\Second\FileSystem. Both of which have the same number & type of arguments in their constructors.

Ordinarily, when running tests as standard, this will immediately be picked up and cause an error. It's possible when running fastest that these two classes will never be around each other at any time during testing, and the test will pass. Tests pass -> Missed it in a peer review -> Deploy to staging -> balls.

Support data providers

Most of my slowest tests depend on dozens of test cases generated via data-providers: is there any way to reproduce those in some way when the data provider output is serializable?

bin/behat --list-scenarios run them instead of list

Hi when i do bin/behat --list-scenarios it does not list it run, as if options was ignore (but opions are present in help)

So bin/behat --list-scenarios | bin/fastest "bin/behat {}" does not work properly

bin/behat --help
Usage:
  behat [options] [--] [<paths>]

Arguments:
  paths                                  Optional path(s) to execute. Could be:
                                                      - a Symfony2 bundle path (@BundleName/)
                                                      - a dir (features/)
                                                      - a feature (*.feature)
                                                      - a scenario at specific line (*.feature:10).
                                                      - all scenarios at or after a specific line (*.feature:10-*).
                                                      - all scenarios at a line within a specific range (*.feature:10-20).
                                                      - a scenarios list file (*.scenarios).

Options:
  -s, --suite=SUITE                      Only execute a specific suite.
  -f, --format=FORMAT                    How to format tests output. pretty is default.
                                                      Available formats are:
                                                      - pretty: Prints the feature as is.
                                                      - progress: Prints one character per step.
                                                      - junit: Outputs the failures in JUnit compatible files.
                                                      You can use multiple formats at the same time. (multiple values allowed)
  -o, --out=OUT                          Write format output to a file/directory instead of
                                                      STDOUT (output_path). You can also provide different
                                                      outputs to multiple formats. (multiple values allowed)
      --format-settings=FORMAT-SETTINGS  Set formatters parameters using json object.
                                                      Keys are parameter names, values are values. (multiple values allowed)
      --init                             Initialize all registered test suites.
      --lang=LANG                        Print output in particular language.
      --name=NAME                        Only executeCall the feature elements which match part
                                                      of the given name or regex. (multiple values allowed)
      --tags=TAGS                        Only executeCall the features or scenarios with tags
                                                      matching tag filter expression. (multiple values allowed)
      --role=ROLE                        Only executeCall the features with actor role matching
                                                      a wildcard.
      --story-syntax                     Print *.feature example.
                                                      Use --lang to see specific language.
  -d, --definitions=DEFINITIONS          Print all available step definitions:
                                                      - use --definitions l to just list definition expressions.
                                                      - use --definitions i to show definitions with extended info.
                                                      - use --definitions 'needle' to find specific definitions.
                                                      Use --lang to see definitions in specific language.
      --append-snippets                  Appends snippets for undefined steps into main context.
      --no-snippets                      Do not print snippets for undefined steps after stats.
      --strict                           Passes only if all tests are explicitly passing.
      --order=ORDER                      Set an order in which to execute the specifications (this will result in slower feedback).
      --rerun                            Re-run scenarios that failed during last execution.
      --stop-on-failure                  Stop processing on first failed scenario.
      --dry-run                          Invokes formatters without executing the tests and hooks.
      --list-features                    Output a list of feature files to be executed by Behat
      --list-scenarios                   Output a list of individual scenarios to be executed by Behat

My behat config

default:
  calls:
    error_reporting: 16383 # E_ALL & ~E_USER_DEPRECATED
  suites:
    default:
      contexts:
        - EntityContext
        - AuthenticationContext
        - DoctrineContext
        - Sanpi\Behatch\Context\JsonContext
        - Sanpi\Behatch\Context\RestContext
        - Knp\FriendlyContexts\Context\AliceContext
        - Behat\MinkExtension\Context\MinkContext

  extensions:
    Liuggio\Fastest\Behat\ListFeaturesExtension\Extension: ~

    Behat\Symfony2Extension:
      kernel:
        debug: true
        env: "test"

    Behat\MinkExtension:
      sessions:
        default:
          symfony2: ~

    Sanpi\Behatch\Extension: ~

    Knp\FriendlyContexts\Extension:

My installation

behat/behat                              v3.1.0             Scenario-oriented BDD framework for PHP 5.3
behat/gherkin                            v4.4.1             Gherkin DSL parser for PHP 5.3
behat/mink                               v1.7.1             Browser controller/emulator abstraction for PHP
behat/mink-browserkit-driver             v1.3.2             Symfony2 BrowserKit driver for Mink framework
behat/mink-extension                     v2.2               Mink extension for Behat
behat/symfony2-extension                 2.1.1              Symfony2 framework extension for Behat
behat/transliterator                     v1.1.0             String transliterator
behatch/contexts                         dev-master 627cbe1 Behatch contexts
liuggio/fastest                          1.3.2              Simple parallel testing execution... with some goodies for functional tests.

I"m running php7

php --version
PHP 7.0.4-7ubuntu2 (cli) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2016, by Zend Technologies

Re-enable -b before command

Execute a process before consuming the queue, it executes this command once per process, useful for init schema and load fixtures.

Adding Peer Servers

Is it possible, to use multi server cores from other peer like in parallel?

Behat tests never end

Hello

I'm running Behat and Mink extension all latest versions. with Symfony 3.4.
Also, I'm using the latest Selenium in Docker image in Hub mode with 2 Chrome nodes.
Running in parallel per feature. DB refreshed on every feature run - so tests are isolated per process and per feature.
It works well on different suites.
But when I run it on a main and biggest suite - it stuck and never ends.

2	51/54	✔	25 s 249 ms	features/backend/3_email_report.feature
1	52/54	✔	15 s 448 ms	features/backend/12_account_select.feature

...

Nevertheless when I run the same suite in normal mode with Behat or in 1 process with fastest - it works, all green.

Trying to think about the issue.
The test, which stucks uses iframe on the page. Also, all our scenarios are marked with @javascript tag, so it fails on js error.
Could it be the issue with fastest that js error is not recognized?
Could it be the issue with use of iframe?
Could it be issue with Selenium and hub mode?
Any ideas on how to debug?

Part of my behat config

extensions:
    Liuggio\Fastest\Behat\ListFeaturesExtension\Extension: ~
    Behat\Symfony2Extension:
        kernel:
            env: accept
            debug: false
    Behat\MinkExtension:
        base_url: http://gogogo.loc:81/
        selenium2:
            wd_host: http://selenium:4444/wd/hub
            capabilities:
                version: ''
                chrome:
                    switches:
                        - "--disable-gpu"
#                        can be faster, but without VNC
#                        - "--headless"
#                        - "--no-sandbox"
                browser: chrome
                browserName: chrome
        javascript_session: selenium2
        browser_name: chrome
  gherkin:
    cache: ~

PDOException: SQLSTATE[HY000] [2002] No such file or directory

Hi, I tried to integrate this project into a big functional tested application. But Doctrine does not seem to work:

Caused by
Doctrine\DBAL\Driver\PDOException: SQLSTATE[HY000] [2002] No such file or directory

/Users/hidden/projects/hidden/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:47
/Users/hidden/projects/hidden/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOMySql/Driver.php:45
/Users/hidden/projects/hidden/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:360
/Users/hidden/projects/hidden/vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php:1166
/Users/hidden/projects/hidden/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:330
/Users/hidden/projects/hidden/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:340
/Users/hidden/projects/hidden/app/cache/test/jms_diextra/doctrine/EntityManager_5583cf32437bc.php:305
/Users/hidden/projects/hidden/src/hidden/hiddenBundle/Tests/Controller/TmpEntities.php:73
/Users/hidden/projects/hidden/src/hidden/hiddenBundle/Tests/Controller/TmpEntities.php:323
/Users/hidden/projects/hidden/src/hidden/hiddenBundle/Tests/Controller/DogControllerTest.php:12
/Users/hidden/projects/hidden/src/hidden/hiddenBundle/Tests/Controller/DogControllerTest.php:83
/Users/hidden/projects/hidden/src/hidden/hiddenBundle/Tests/Controller/DogControllerTest.php:118

TmpEntities.php:73 does $this->em->flush();.

We get the EntityManager via:

$this->em = static::$kernel->getContainer()
            ->get('doctrine')
            ->getManager()
        ;

Any ideas?

Symfony 2.3
Doctrine 2.4.7
DBAL 2.5.1
PHPUnit 4.7.3
OSX 10.10.3

Placeholder manipulation

Hello,

I'm trying to use fastest to generate phpunit code coverage with phpcov at the end to merge the generated .cov files.

I've tried running the following command, which does not work. My guess is that a Process is unable to spawn/execute the subcommand within the backticks.

find app/tests -name "*Test.php" | vendor/bin/fastest "php vendor/bin/phpunit --coverage-php cov/echo {}.cov | sed 's|/|_|g' {}" -vvv

My question is, how can we do placeholder manipulation in order to be able to do things such as replacing / with _?

[RFC] stable release?

We are using fastest with phpunit in our daily job and seems pretty stable,

For me the stable version could be done when #20 will be fixed,
and the pipe thing will be closed,
I'd like to know the dev/user point of view.

/cc @giorrrgio @diegosainz @wcluijt

Behat broken after installing extension

I'm using behat 3.2.1, as soon as I install the extension as the README says, behat does not work anymore. It doesn't give output regardless of the command run

    $ vendor/bin/behat -V
    behat version 3.2.1

After putting the extension on behat.yml Liuggio\Fastest\Behat2\ListFeaturesExtension\Extension: ~, any behat command terminate immediately with exit code 255 (and not output)

    $ #vendor/bin/behat -V
    #

The same for any other behat command (run tests, see scenarios, etc...)

Behat 3 compatiblity

Currently, this project only supports Behat1 and Behat2. A Behat 3 support would be really nice :-)

Behat broken logs with --list-scenarios

Hi,

I am using your behat extension for testing, and later building logs because i'm using Jenkins CI.
Command is this:

./bin/behat -c app/config/behat.yml "@AppWebBundle" --list-scenarios |
    ./bin/fastest --verbose --preserve-order
    "./bin/behat --format=junit --out=build/logs/behat -c app/config/behat.yml -v {};

Tests pass, but when logs are built they don't have proper content. Examples:

<?xml version="1.0" encoding="UTF-8"?>
<testsuite errors="0" failures="0" skipped="0" name="User can reset his password in case he forgets it." tests="1" time="5.978331">
    <testcase classname="User can reset his password in case he forgets it." name="User exists in the system" time="3.853432" assertions="8">
    </testcase>
</testsuite>
suite>
<?xml version="1.0" encoding="UTF-8"?>
<testsuite errors="0" failures="0" skipped="0" name="Filter users" tests="1" time="13.394022">
    <testcase classname="Filter users" name="Show all users" time="11.175531" assertions="7">
    </testcase>
</testsuite>
uite>
testcase>
</testsuite>

From 76 features, i get this bug for around 30 features, and this breaks my build on Jenkins. When i use
--list-features everything works fine.

Do you know what can be a problem maybe? Thanks.

PHPUnit_Framework_Exception

Hello,

When I run phpunit without fastest, the whole test goes fine and finish successfully

export ENV_TEST_CHANNEL_READABLE='test_1'; vendor/bin/phpunit -c app Tests/Functional/APP/APPTest.php --stop-on-failure --bootstrap Tests/bootstrap-jenkinstest.php -vvv

But when I run

echo "Tests/Functional/APP/APPTest.php" | vendor/bin/fastest "vendor/bin/phpunit -c app {} --bootstrap=Tests/bootstrap-jenkinstest.php" -vvv --before="./initORM.php jenkinstest" -p 1

I get this error:

PHPUnit_Framework_Exception: sh: 1: : Permission denied

I have tried to find out the path that fastest(?)/phpunit might be trying to load, but I haven't been lucky so far.

JUnit not all features are reported in the results file

I have a test suite which contains two feature files and output set to JUnit.
When running the suite with fastest, the .xml result file contains only one of the two features.
When running the suite with Behat without fastest, both features are reported to the results xml.

I am running fastest with the following line:

bin\behat --list-features --suite=api --config=../behat.yml | bin\fastest --preserve-order "bin\behat --config=../behat.yml -f progress -o std -f junit -o results {
}"

When running with fastest, only one of the feature file gets reported in the xml:
<?xml version="1.0" encoding="UTF-8"?> <testsuites name="api"> <testsuite name="API REST 4.0" tests="1" skipped="0" failures="0" errors="0"> <testcase name="Call placeOrder method in 4.0 and verify that order is complete" status="passed"></testcase> </testsuite> </testsuites>

When running with behat, both feature files are reported in the xml:
<?xml version="1.0" encoding="UTF-8"?> <testsuites name="api"> <testsuite name="API REST 5.0" tests="1" skipped="0" failures="0" errors="0"> <testcase name="Call placeOrder method and verify that order is complete" status="passed"></testcase> </testsuite> <testsuite name="API REST 4.0" tests="1" skipped="0" failures="0" errors="0"> <testcase name="Call placeOrder method in 4.0 and verify that order is complete" status="passed"></testcase> </testsuite> </testsuites>

phpunit compatibility

Hello guys, i tried to run liuggio/fastest with phpunit 6.1.3
It cannot be get with composer because of the require statement on line 17
"phpunit/phpunit": "~4.8|~5.4"

I dont want to install the phpunit 6.1.3 externally. So i just added in my fork:
"phpunit/phpunit": "~4.8|~5.4|~6.1"

worked great for me.

Semantic versioning and patch releases

I hate useing dev-master dependencies. It's a bad practice. Please, do another release follwing semantic versioning, it should be v1.0.1 (first patch to 1.0 version).

Also, please keep tagging new releases (patch, for bug fixes, minor for new features, major for BC breaking changes) when merging PRs into master.

Thanks.

Allow diffrent command for rerunning tests

I have a case where some tests fail, becouse of random Segmentation Faults.

Running the same tests with --process-isolation the tests succed.

It would be very useful if I could define a diffrent command for rerunning tests, eg:

bin/fastest -r -o -v "bin/phpunit {}" "bin/phpunit --process-isolation {}"

where the second argument is command for "rerunning tests".

Or maybe a named argument like:
bin/fastest -r -o -v "bin/phpunit {}" --rerun-command="bin/phpunit --process-isolation {}"

Missing Env variables in process cause problems

I've been searching for hours why using fastest my php version seemed wrong, while the same commands in the terminal directly all seem to work.

In the end I found that creating a Process with specific ENV variables, will not include your original ENV variables, in my case causing each process to fail.

Easy to fix in EnvCommandCreator.php
line 16:

return $_ENV + array(

Skipped tests are not reported

I use $this->markTestSkipped(); in several of my tests to skip tests when a debugging tool is not available. But fastest does not detect skipped tests, they are treated as if tests were passed successfully.

fastest should display a warning of something when a test is skipped (and tests marked as risky or incomplete should probably treated in the same way).

use GPU

Fastest could use the GPU driver eg. cuda in order to speedup things :)

@claudio-dalicandro is a kind of master on this and maybe could suggest some good tips and implementation...

Fails with multiple test suites

Given a phpunit.xml like this:

<phpunit
  ...
>

  <testsuites>
    <testsuite name="First suite">
      <directory>path/to/first/suite</directory>
    </testsuite>
    <testsuite name="Second suite">
      <directory>path/to/second/suite</directory>
    </testsuite>
  </testsuites>

</phpunit>

The command fails while it tries to interpret the test suite name as PHP class name:

fastest --xml phpunit.xml


  [ReflectionException]
  Class First suite does not exist


fastest [-p|--process PROCESS] [-b|--before BEFORE] [-x|--xml XML] [-o|--preserve-order] [-r|--rerun-failed] [--no-errors-summary] [--] [<execute>]

ENV variables within SF4

Hmm seems like env variables are not working within symfony 4, for some reason eg. ENV_TEST_CHANNEL_READABLE is not set as it was on 3.x branch.

[documentation] How to run behat 3 tests

Hi, I see some documentation regarding behat 2.* and commits that seem to make it possible to run parallel scenarios with behat 3. Should the actual 2.* documentation work for behat3?

I would really appreciate some help please.

cc @aitboudad

Behat integration

Just to get started on the discussion...

The goal of the feature would be to easily feed fastest with all the individual feature files (*.feature) that Behat would execute as a whole in a normal run.

One way we are experimenting to accomplish this is to write a Behat extension that will add a command line option to behat (i.e. --list-features) that outputs to stdout a list of all individual *.feature files that can be used to feed the input of fastest.

For example:

behat src/Acme/ --list-features | fastest behat {}

The extension currently calls behat's gherkin service in order to use the same feature loaders and filters that Behat would use in a normal run and extract the individual file names. Something along these lines:

    // ListFeaturesProcessor class

    $featureFiles = [];
    $featurePaths = $this->container->get('behat.console.command')->getFeaturesPaths();
    foreach($featurePaths as $featurePath) {

        /* @var $featureNodes \Behat\Gherkin\Node\FeatureNode[] */
        $featureNodes = $this->container->get('gherkin')->load($featurePath);
        foreach($featureNodes as $featureNode) {
            $featureFiles[] = $featureNode->getFile();
        }       
   }

The extension would have to be enabled in the behat.yml file.

In related but different theme about there is also the need to include Mink support for browser-side tests, so browser requests go to the correct backend database depending on the environment that made the request. Currently we are injecting (with a somewhat hacky method) into the session cookie the fastest database name in order to set the environment variable ENV_TEST_CHANNEL_READABLE in web/app_test.php just before booting the kernel:

// web/app_test.php
$testDbEnvVarName = 'ENV_TEST_CHANNEL_READABLE';
$cookieIndexName = "_fastest_$testDbEnvVarName";
if (isset($_COOKIE[$cookieIndexName])) {
    $sanitizedEnv = preg_replace('/a-z_0-9\-/i', '', $_COOKIE[$cookieIndexName]);
    putenv("$testDbEnvVarName=$sanitizedEnv");
}

Do you have in mind other approaches that would be better? Am I overlooking something that won't work in other use cases?

Create a PHAR file

I'm curious that i nothing found about that here. But have you any plans to create a PHAR file as second usage option? Because fastest can be used "globally" for a different kind of projects.

So there are no reasons to add this in the require-dev part in a project composer.json. That would also solve some potential dependency bugs (for example with Symfony projects that use an other console component version) because of dependency encapsulation in the PHAR file.

real stream on piping

As reported in PR #7 pipe has some problem.

Now the pipe read all the data from the input and then processes it,
but this comes with some disadvantages.

A good solution would be a real Pipe stream, when there's new input the new data is added to the queue.

Support for Symfony 4

Symfony 4 was just released and I cannot update to that because currently package.json contains following:

"symfony/console": "~2.7|~3.0",
"symfony/stopwatch": "~2.7|~3.0",
"symfony/process": "~2.7|~3.0",

Fastest should fail fast if the before script fails

If the given --before script fails, I think fastest should exit early with the error. Otherwise you have a whole testsuite that runs with a broken environment.

I had a quick look at patching this, but looks like the before process is treated like any other test process, so might require a different execution strategy.

Can't seem to ever access fastest ENV vars

I'm currently running a phpunit test suite with its own xml file, and testing against laravel.

I'm trying to setup the suite so that it creates/destroys a database based on the channel the process is using, but the relevant env vars are never available.

Any ideas?

Wrong test count when using -b option

Test count (106 shuffled test classes into the queue) is correct, but actual files that are shown also adds those -b files to that queuee. So this causes that runned files are offset as many as process you have defined.

TravisCI logs below to demonstrate this.

$ find tests/ -name "*Test.php" | php ./vendor/bin/fastest -v -p 8 -b "php ./tests/bootstrap.php" "php ./vendor/bin/phpunit {} -c phpunit.fastest.xml --coverage-php build/fastest/{n}.cov;"
- 106 shuffled test classes into the queue.
- Will be consumed by 8 parallel Processes.
1/106	✔	2 s 893 ms	php ./tests/bootstrap.php
2/106	✔	2 s 959 ms	php ./tests/bootstrap.php
3/106	✔	2 s 316 ms	php ./tests/bootstrap.php
4/106	✔	2 s 304 ms	php ./tests/bootstrap.php
5/106	✔	2 s 546 ms	php ./tests/bootstrap.php
6/106	✔	2 s 283 ms	php ./tests/bootstrap.php
7/106	✔	2 s 703 ms	php ./tests/bootstrap.php
8/106	✔	2 s 524 ms	php ./tests/bootstrap.php
9/106	✔	468 ms	tests/Unit/Utils/JSONTest.php
10/106	✔	529 ms	tests/Unit/Rest/RequestHandlerTest.php
11/106	✔	839 ms	tests/Integration/Entity/RoleTest.php
12/106	✔	408 ms	tests/Unit/Rest/SearchTermTest.php
13/106	✔	364 ms	tests/Integration/Form/Type/Rest/User/UserPatchTypeTest.php
14/106	✔	464 ms	tests/Integration/Form/Type/Console/UserGroupTypeTest.php
15/106	✔	1 s 446 ms	tests/Unit/IntegrityTest.php
16/106	✔	348 ms	tests/Integration/Security/ApiKeyAuthenticatorTest.php
17/106	✔	1 s 93 ms	tests/Integration/Repository/LogRequestRepositoryTest.php
18/106	✔	378 ms	tests/Unit/Utils/Tests/PHPUnitUtilTest.php
19/106	✔	445 ms	tests/Integration/DTO/ApiKeyTest.php
20/106	✔	864 ms	tests/Integration/EventSubscriber/BodySubscriberTest.php
21/106	✔	683 ms	tests/Integration/Rest/Traits/Actions/Root/ActionTest.php
22/106	✔	539 ms	tests/Integration/Form/Type/Console/UserTypeTest.php
23/106	✔	993 ms	tests/Integration/Repository/LogLoginRepositoryTest.php
24/106	✔	383 ms	tests/Integration/Form/DataTransformer/RoleTransformerTest.php
25/106	✔	341 ms	tests/Integration/Utils/HealthzServiceTest.php
26/106	✔	382 ms	tests/Integration/Validator/Constraints/UniqueEmailValidatorTest.php
27/106	✔	548 ms	tests/Integration/Rest/Traits/Actions/User/ActionTest.php
28/106	✔	1 s 213 ms	tests/Integration/Repository/HealthzRepositoryTest.php
29/106	✔	622 ms	tests/Integration/Rest/Traits/Methods/FindOneMethodTest.php
30/106	✔	2 s 624 ms	tests/Integration/Repository/GenericRepositoryTest.php
31/106	✔	847 ms	tests/Integration/Rest/Traits/Actions/Admin/ActionTest.php
32/106	✔	538 ms	tests/Integration/Rest/Traits/Methods/PatchMethodTest.php
33/106	✔	3 s 683 ms	tests/Integration/Rest/RepositoryHelperTest.php
34/106	✔	5 s 832 ms	tests/Integration/Entity/DateDimensionTest.php
35/106	✔	777 ms	tests/Integration/Resource/LogRequestResourceTest.php
36/106	✔	784 ms	tests/Integration/Resource/DateDimensionResourceTest.php
37/106	✔	8 s 179 ms	tests/Integration/Entity/LogRequestTest.php
38/106	✔	8 s 333 ms	tests/Functional/Controller/UserGroupControllerTest.php
39/106	✔	1 s 360 ms	tests/Functional/Security/UserProviderTest.php
40/106	✔	1 s 80 ms	tests/Integration/Repository/DateDimensionRepositoryTest.php
41/106	✔	542 ms	tests/Integration/Entity/HealthzTest.php
42/106	✔	1 s 92 ms	tests/Integration/Repository/RoleRepositoryTest.php
43/106	✔	932 ms	tests/Integration/Controller/UserControllerTest.php
44/106	✔	1 s 428 ms	tests/Integration/SchemaTest.php
45/106	✔	454 ms	tests/Integration/Rest/Traits/Methods/FindMethodTest.php
46/106	✔	862 ms	tests/Integration/EventSubscriber/RequestSubscriberTest.php
47/106	✔	4 s 738 ms	tests/Functional/DocumentationTest.php
48/106	✔	518 ms	tests/Integration/Form/Type/Console/ApiKeyTypeTest.php
49/106	✔	1 s 933 ms	tests/Functional/Controller/DefaultControllerTest.php
50/106	✔	1 s 339 ms	tests/Integration/Rest/ResponseHandlerTest.php
51/106	✔	1 s 452 ms	tests/Integration/Security/UserProviderTest.php
52/106	✔	1 s 99 ms	tests/Integration/Repository/UserGroupRepositoryTest.php
53/106	✔	487 ms	tests/Integration/Rest/Traits/Methods/CountMethodTest.php
54/106	✔	996 ms	tests/Integration/Controller/UserGroupControllerTest.php
55/106	✔	762 ms	tests/Integration/Rest/Traits/Actions/Authenticated/ActionTest.php
56/106	✔	426 ms	tests/Integration/DTO/GenericDtoTest.php
57/106	✔	543 ms	tests/Integration/Rest/Traits/Methods/DeleteMethodTest.php
58/106	✔	447 ms	tests/Integration/EventSubscriber/AuthenticationSuccessSubscriberTest.php
59/106	✔	439 ms	tests/Integration/Rest/ControllerTest.php
60/106	✔	7 s 319 ms	tests/Integration/Entity/UserTest.php
61/106	✔	8 s 418 ms	tests/Functional/Repository/RoleRepositoryTest.php
62/106	✔	380 ms	tests/Integration/Form/DataTransformer/UserGroupTransformerTest.php
63/106	✔	386 ms	tests/Integration/Utils/LoginLoggerTest.php
64/106	✔	992 ms	tests/Functional/Repository/LogRequestRepositoryTest.php
65/106	✔	509 ms	tests/Integration/EventSubscriber/AuthenticationFailureSubscriberTest.php
66/106	✔	830 ms	tests/Integration/Resource/LogLoginResourceTest.php
67/106	✔	635 ms	tests/Integration/Rest/Traits/Methods/UpdateMethodTest.php
68/106	✔	888 ms	tests/Integration/Resource/ApiKeyResourceTest.php
69/106	✔	15 s 132 ms	tests/Functional/Controller/ApiKeyControllerTest.php
70/106	✔	6 s 922 ms	tests/Integration/Entity/LogLoginTest.php
71/106	✔	461 ms	tests/Integration/Rest/Traits/Methods/IdsMethodTest.php
72/106	✔	940 ms	tests/Integration/Controller/ApiKeyControllerTest.php
73/106	✔	405 ms	tests/Integration/Form/Type/Rest/User/UserCreateTypeTest.php
74/106	✔	743 ms	tests/Integration/Resource/UserResourceTest.php
75/106	✔	454 ms	tests/Integration/DTO/UserGroupTest.php
76/106	✔	11 s 512 ms	tests/Functional/Repository/HealthzRepositoryTest.php
77/106	✔	1 s 411 ms	tests/Unit/Security/ApiKeyUserTest.php
78/106	✔	489 ms	tests/Integration/DTO/UserTest.php
79/106	✔	787 ms	tests/Integration/Resource/HealthzResourceTest.php
80/106	✔	1 s 46 ms	tests/Integration/Repository/UserRepositoryTest.php
81/106	✔	12 s 310 ms	tests/Functional/Repository/UserRepositoryTest.php
82/106	✔	724 ms	tests/Integration/Resource/RoleResourceTest.php
83/106	✔	349 ms	tests/Unit/Entity/RoleTest.php
84/106	✔	4 s 864 ms	tests/Integration/Entity/UserGroupTest.php
85/106	✔	399 ms	tests/Integration/Validator/Constraints/UniqueUsernameValidatorTest.php
86/106	✔	373 ms	tests/Integration/EventSubscriber/JWTCreatedSubscriberTest.php
87/106	✔	405 ms	tests/Integration/Security/ApiKeyUserProviderTest.php
88/106	✔	644 ms	tests/Integration/Resource/UserGroupResourceTest.php
89/106	✔	1 s 426 ms	tests/Unit/Security/RolesServiceTest.php
90/106	✔	628 ms	tests/Integration/Rest/Traits/Actions/Logged/ActionTest.php
91/106	✔	351 ms	tests/Integration/Doctrine/DBAL/Types/UTCDateTimeTypeTest.php
92/106	✔	484 ms	tests/Integration/Utils/RequestLoggerTest.php
93/106	✔	427 ms	tests/Integration/Doctrine/DBAL/Types/EnumLogLoginTypeTest.php
94/106	✔	655 ms	tests/Integration/Rest/Traits/Actions/Anon/ActionTest.php
95/106	✔	8 s 275 ms	tests/Integration/EventSubscriber/UserEntitySubscriberTest.php
96/106	✔	939 ms	tests/Integration/Repository/ApiKeyRepositoryTest.php
97/106	✔	3 s 827 ms	tests/Integration/Resource/GenericResourceTest.php
98/106	✔	444 ms	tests/Integration/EventSubscriber/JWTDecodedSubscriberTest.php
99/106	✔	18 s 177 ms	tests/Functional/Controller/RoleControllerTest.php
100/106	✔	478 ms	tests/Integration/Form/Type/Rest/User/UserUpdateTypeTest.php
101/106	✔	511 ms	tests/Integration/EventSubscriber/ExceptionSubscriberTest.php
102/106	✔	5 s 779 ms	tests/Integration/Entity/ApiKeyTest.php
103/106	✔	567 ms	tests/Integration/Form/Type/Rest/UserGroup/UserGroupTypeTest.php
104/106	✔	924 ms	tests/Integration/Controller/RoleControllerTest.php
105/106	✔	372 ms	tests/Integration/Controller/AuthControllerTest.php
106/106	✔	782 ms	tests/Integration/Rest/Traits/Methods/CreateMethodTest.php
107/106	✔	1 min 29 s	tests/Functional/Controller/UserControllerTest.php
108/106	✔	1 min 1 s 904 ms	tests/Functional/Controller/AuthControllerTest.php
109/106	✔	2 min 8 s 281 ms	tests/Functional/Rest/Traits/Actions/AdminActionsTest.php
110/106	✔	1 min 21 s 855 ms	tests/Functional/Rest/Traits/Actions/RootActionsTest.php
111/106	✔	2 min 6 s 99 ms	tests/Functional/Rest/Traits/Actions/UserActionsTest.php
112/106	✔	2 min 45 s 7 ms	tests/Functional/Rest/Traits/Actions/LoggedActionsTest.php
113/106	✔	2 min 49 s 603 ms	tests/Functional/Rest/Traits/Actions/AuthenticatedActionsTest.php
114/106	✔	2 min 34 s 667 ms	tests/Functional/Rest/Traits/Actions/AnonActionsTest.php
 ✔ You are great!
 Time: 3 minutes 30 seconds 551 milliseconds, Memory: 4.00 MiB

Slower to run than native PHPUnit command

I came across fastest today and sounded promising, exactly what our team were looking for. I gave it a go but for my surprise, it takes twice the time to run the unit tests. The project is powered by Symfony2 and using LiipFunctionalTestBundle. I executed the following command to run the tests:

find src/Alpha/ -name "*Test.php" | php bin/fastest -o "php bin/phpunit -c app {};"

And takes over 4 minutes to run all the 235 tests. The phpunit command takes almost 2 minutes to run the same tests. Fastest is using two processes and I get two sqlite files for the database, so it seems to be set up properly. How can I debug why it is so slow? What might causing it? Both tests run under on the same machine with the same environment, with xdebug on.

support of PHP 7.3

Can you recheck fastest with PHP 7.3?
Looks like it broken when use 2+ parallel processes, but I can't find the reason... Part of unit tests return error.

Tested under Windows.

Problem with setting header in symfony

Hi,

I have use opensoure sylius ecommerce system, and i want use fastest. But we use selenium or local server to test (using behat). How i can put header or cookie on start to every test? i dont want change every test. I'm trying this more than 4 days, and still have problem :)

Cannot open phpunit testsuite directories

Fastest is not able to open testsuite directories containing wildcard characters

2 failures.

[1] ../src/*/Bundle/*Bundle/TestsCannot open file "../src/*/Bundle/*Bundle/Tests.php".

[2] ../src/*/*Bundle/TestsCannot open file "../src/*/*Bundle/Tests.php".

An example of the wildcard containing xml file can be found a symfony/symfony

Re-enable xml input

Read input from a phpunit xml file from the '' collection. Note: it is not used for consuming.

The idea is to better integrate Phpunit in the v2.0 as tests provider and as output

Socket failure when run in fastest

Did not have time to investigate much but I have a test running $socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); that works fine via phpunit but when I run via fastest it fails with:

socket_create(): Unable to create socket [0]: The requested service provider could not be loaded or initialized.

PHPUnit Logging

We're logging our testresults as junit xml files:
phpunit.xml:

<logging>
    <log type="junit" target="build/phpunit/junit.xml" logIncompleteSkipped="false"/>
</logging>

But since we're using fastest, the junit.xml file gets overwritten for each test and therefore does not contain the results of the tests that ran before the last one.
Is there any kind of workaround?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.