polytrix 0.0.1 → 0.1.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/.rspec +1 -6
- data/.rubocop-todo.yml +19 -0
- data/.rubocop.yml +10 -0
- data/.travis.yml +11 -0
- data/Gemfile +0 -16
- data/README.md +119 -28
- data/Rakefile +18 -123
- data/bin/polytrix +5 -0
- data/doc-src/_markdown.md +5 -0
- data/doc-src/default_bootstrap.md +13 -0
- data/docs/influences.md +28 -0
- data/docs/samples/code2doc/java/HelloWorld.md +13 -0
- data/docs/samples/code2doc/java/Quine.md +33 -0
- data/docs/samples/code2doc/python/hello_world.md +3 -0
- data/docs/samples/code2doc/python/quine.md +4 -0
- data/docs/samples/code2doc/ruby/hello_world.md +7 -0
- data/features/execution.feature +67 -0
- data/features/fixtures/configs/empty.yml +12 -0
- data/features/fixtures/configs/hello_world.yml +10 -0
- data/features/fixtures/spec/polytrix_merge.rb +5 -0
- data/features/fixtures/spec/polytrix_spec.rb +10 -0
- data/features/reporting.feature +140 -0
- data/features/step_definitions/sdk_steps.rb +12 -0
- data/features/support/env.rb +8 -0
- data/lib/polytrix/challenge.rb +20 -7
- data/lib/polytrix/challenge_runner.rb +9 -44
- data/lib/polytrix/cli/add.rb +67 -0
- data/lib/polytrix/cli/report.rb +88 -0
- data/lib/polytrix/cli/reports/hash_reporter.rb +30 -0
- data/lib/polytrix/cli/reports/json_reporter.rb +14 -0
- data/lib/polytrix/cli/reports/markdown_reporter.rb +23 -0
- data/lib/polytrix/cli/reports/yaml_reporter.rb +14 -0
- data/lib/polytrix/cli.rb +158 -0
- data/lib/polytrix/configuration.rb +65 -4
- data/lib/polytrix/core/file_system_helper.rb +75 -0
- data/lib/polytrix/core/implementor.rb +31 -3
- data/lib/polytrix/documentation/code_segmenter.rb +168 -0
- data/lib/polytrix/documentation/comment_styles.rb +87 -0
- data/lib/polytrix/documentation/helpers/code_helper.rb +85 -0
- data/lib/polytrix/documentation/view_helper.rb +21 -0
- data/lib/polytrix/documentation_generator.rb +59 -10
- data/lib/polytrix/executor.rb +89 -0
- data/lib/polytrix/logger.rb +17 -0
- data/lib/polytrix/manifest.rb +64 -7
- data/lib/polytrix/result.rb +16 -2
- data/lib/polytrix/rspec/documentation_formatter.rb +41 -16
- data/lib/polytrix/rspec/yaml_report.rb +51 -0
- data/lib/polytrix/rspec.rb +32 -53
- data/lib/polytrix/runners/middleware/feature_executor.rb +4 -3
- data/lib/polytrix/runners/middleware/setup_env_vars.rb +6 -4
- data/lib/polytrix/validation.rb +20 -0
- data/lib/polytrix/validations.rb +23 -0
- data/lib/polytrix/validator.rb +20 -0
- data/lib/polytrix/validator_registry.rb +34 -0
- data/lib/polytrix/version.rb +1 -1
- data/lib/polytrix.rb +125 -22
- data/polytrix.gemspec +7 -2
- data/polytrix.rb +6 -0
- data/polytrix_tests.yml +20 -0
- data/resources/code_sample.tt +2 -0
- data/samples/.gitignore +2 -0
- data/samples/_markdown.md +5 -0
- data/samples/default_bootstrap.rb +14 -0
- data/samples/polytrix.rb +28 -0
- data/samples/polytrix_cli.sh +7 -0
- data/samples/polytrix_tests.yml +10 -0
- data/{sdks/fog → samples}/scripts/bootstrap +0 -2
- data/samples/scripts/wrapper +7 -0
- data/samples/sdks/custom/polytrix.yml +2 -0
- data/samples/sdks/java/.gitignore +2 -0
- data/samples/sdks/java/build.gradle +14 -0
- data/samples/sdks/java/challenges/HelloWorld.java +10 -0
- data/samples/sdks/java/challenges/Quine.java +31 -0
- data/samples/sdks/java/code_sample.tt +11 -0
- data/samples/sdks/java/scripts/bootstrap +2 -0
- data/samples/sdks/java/scripts/wrapper +8 -0
- data/samples/sdks/python/challenges/hello_world.py +2 -0
- data/samples/sdks/python/challenges/quine.py +2 -0
- data/{sdks/pkgcloud → samples/sdks/python}/scripts/wrapper +1 -1
- data/samples/sdks/ruby/challenges/hello_world.rb +4 -0
- data/scripts/bootstrap +1 -9
- data/scripts/wrapper +7 -0
- data/spec/fabricators/challenge_fabricator.rb +17 -0
- data/spec/fabricators/manifest_fabricator.rb +50 -0
- data/spec/fabricators/validator_fabricator.rb +12 -0
- data/spec/fixtures/{polytrix.yml → polytrix_tests.yml} +0 -0
- data/spec/fixtures/src-doc/_scenario.md.erb +1 -0
- data/spec/polytrix/challenge_runner_spec.rb +3 -3
- data/spec/polytrix/challenge_spec.rb +3 -4
- data/spec/polytrix/cli_spec.rb +39 -0
- data/spec/polytrix/configuration_spec.rb +45 -1
- data/spec/polytrix/documentation/helpers/code_helper_spec.rb +120 -0
- data/spec/polytrix/documentation_generator_spec.rb +41 -20
- data/spec/polytrix/file_finder_spec.rb +4 -3
- data/spec/polytrix/implementor_spec.rb +33 -0
- data/spec/polytrix/manifest_spec.rb +32 -14
- data/spec/polytrix/middleware/feature_executor_spec.rb +1 -1
- data/spec/polytrix/result_spec.rb +49 -0
- data/spec/polytrix/validations_spec.rb +16 -0
- data/spec/polytrix/validator_registry_spec.rb +39 -0
- data/spec/polytrix/validator_spec.rb +63 -0
- data/spec/polytrix_spec.rb +33 -7
- data/spec/spec_helper.rb +14 -1
- data/spec/thor_spy.rb +64 -0
- metadata +177 -160
- data/.rspec_parallel +0 -10
- data/Vagrantfile +0 -41
- data/features/0_identity_spec.rb +0 -40
- data/features/1_cloud_files_spec.rb +0 -48
- data/features/2_servers_spec.rb +0 -19
- data/features/features_helper.rb +0 -46
- data/features/helpers/cloudfiles_helper.rb +0 -31
- data/features/helpers/pacto_helper.rb +0 -33
- data/features/helpers/teardown_helper.rb +0 -49
- data/features/pacto/extensions/loaders/api_blueprint_loader.rb +0 -63
- data/features/pacto/extensions/loaders/simple_loader.rb +0 -55
- data/features/pacto/extensions/loaders/yaml_or_json_loader.rb +0 -17
- data/features/pacto/extensions/matchers.rb +0 -38
- data/features/phase2/feature_coverage_report.rb +0 -109
- data/features/phase2/run_all_features.rb +0 -14
- data/features/static_site/fixtures/index.html +0 -6
- data/lib/polytrix/challenge_builder.rb +0 -16
- data/lib/polytrix/core/file_finder.rb +0 -43
- data/lib/polytrix/core/result_tracker.rb +0 -25
- data/lib/polytrix/runners/middleware/pacto.rb +0 -59
- data/packer/.gitignore +0 -3
- data/packer/Berksfile +0 -15
- data/packer/Gemfile +0 -5
- data/packer/Vagrantfile +0 -128
- data/packer/cookbooks/drg/metadata.rb +0 -27
- data/packer/cookbooks/drg/recipes/admins.rb +0 -22
- data/packer/cookbooks/drg/recipes/default.rb +0 -9
- data/packer/cookbooks/drg/recipes/dotnet.rb +0 -4
- data/packer/cookbooks/drg/recipes/golang.rb +0 -4
- data/packer/cookbooks/drg/recipes/java.rb +0 -5
- data/packer/cookbooks/drg/recipes/php.rb +0 -10
- data/packer/cookbooks/drg/recipes/ruby.rb +0 -29
- data/packer/cookbooks/drg/recipes/system.rb +0 -13
- data/packer/create_box.sh +0 -10
- data/packer/http/preseed.cfg +0 -87
- data/packer/packer.json +0 -91
- data/packer/scripts/root_setup.sh +0 -37
- data/packer/scripts/setup.sh +0 -32
- data/pacto/config/pacto_server.rb +0 -40
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/extensions.json +0 -64
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/flavors/id.json +0 -100
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/images/id.json +0 -176
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers/id.json +0 -189
- data/pacto/contracts/dfw.servers.api.rackspacecloud.com/v2/account_id/servers.json +0 -63
- data/pacto/contracts/dns.api.rackspacecloud.com/v1.0/_tenant_id/domains.json +0 -62
- data/pacto/contracts/identity.api.rackspacecloud.com/v2.0/tokens.json +0 -192
- data/pacto/contracts/monitoring.api.rackspacecloud.com/v1.0/_tenant_id/account.json +0 -39
- data/pacto/contracts/ord.autoscale.api.rackspacecloud.com/v1.0/_tenant_id/groups.json +0 -38
- data/pacto/contracts/ord.blockstorage.api.rackspacecloud.com/v1/_tenant_id/volumes.json +0 -30
- data/pacto/contracts/ord.databases.api.rackspacecloud.com/v1.0/_tenant_id/instances.json +0 -30
- data/pacto/contracts/ord.loadbalancers.api.rackspacecloud.com/v1.0/_tenant_id/loadbalancers.json +0 -114
- data/pacto/contracts/ord.queues.api.rackspacecloud.com/v1/_tenant_id/queues.json +0 -13
- data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/os-networksv2.json +0 -46
- data/pacto/contracts/ord.servers.api.rackspacecloud.com/v2/_tenant_id/servers/detail.json +0 -230
- data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account/container/object.json +0 -15
- data/pacto/contracts/storage101.dfw1.clouddrive.com/v1/mosso_account.json +0 -43
- data/pacto/contracts/storage101.ord1.clouddrive.com/v1/_mosso_id.json +0 -44
- data/pacto/pacto_server.rb +0 -100
- data/pacto/rackspace_uri_map.yaml +0 -229
- data/scripts/cibuild +0 -4
- data/sdks/fog/.gitignore +0 -1
- data/sdks/fog/Gemfile +0 -5
- data/sdks/fog/challenges/all_connections.rb +0 -45
- data/sdks/fog/challenges/authenticate_token.rb +0 -15
- data/sdks/fog/challenges/cdn_enable_container.rb +0 -20
- data/sdks/fog/challenges/create_a_container.rb +0 -17
- data/sdks/fog/challenges/create_server.rb +0 -36
- data/sdks/fog/challenges/get_object_metadata.rb +0 -13
- data/sdks/fog/challenges/list_containers.rb +0 -10
- data/sdks/fog/challenges/provision_scalable_webapp.rb +0 -30
- data/sdks/fog/challenges/upload_folder.rb +0 -25
- data/sdks/fog/scripts/bootstrap.ps1 +0 -1
- data/sdks/fog/scripts/wrapper +0 -2
- data/sdks/fog/scripts/wrapper.ps1 +0 -1
- data/sdks/gophercloud/.gitignore +0 -2
- data/sdks/gophercloud/challenges/authenticate_token.go +0 -23
- data/sdks/gophercloud/scripts/bootstrap +0 -6
- data/sdks/gophercloud/scripts/wrapper +0 -10
- data/sdks/jclouds/.gitignore +0 -1
- data/sdks/jclouds/challenges/AuthenticateToken.java +0 -115
- data/sdks/jclouds/pom.xml +0 -34
- data/sdks/jclouds/scripts/bootstrap +0 -3
- data/sdks/jclouds/scripts/wrapper +0 -7
- data/sdks/openstack.net/.gitignore +0 -4
- data/sdks/openstack.net/.nuget/Microsoft.Build.dll +0 -0
- data/sdks/openstack.net/.nuget/NuGet.Config +0 -6
- data/sdks/openstack.net/.nuget/NuGet.exe +0 -0
- data/sdks/openstack.net/.nuget/NuGet.targets +0 -136
- data/sdks/openstack.net/Challenge.cs +0 -10
- data/sdks/openstack.net/RunChallenge.cs +0 -19
- data/sdks/openstack.net/challenges/AuthenticateToken.cs +0 -24
- data/sdks/openstack.net/challenges/Weird.cs +0 -133
- data/sdks/openstack.net/openstack.net.csproj +0 -58
- data/sdks/openstack.net/openstack.net.sln +0 -27
- data/sdks/openstack.net/openstack.net.userprefs +0 -8
- data/sdks/openstack.net/packages.config +0 -6
- data/sdks/openstack.net/scripts/bootstrap +0 -2
- data/sdks/openstack.net/scripts/bootstrap.ps1 +0 -2
- data/sdks/openstack.net/scripts/wrapper +0 -7
- data/sdks/openstack.net/scripts/wrapper.ps1 +0 -1
- data/sdks/php-opencloud/.gitignore +0 -4
- data/sdks/php-opencloud/challenges/all_connections.php +0 -64
- data/sdks/php-opencloud/challenges/authenticate_token.php +0 -14
- data/sdks/php-opencloud/challenges/create_server.php +0 -39
- data/sdks/php-opencloud/challenges/get_object_metadata.php +0 -19
- data/sdks/php-opencloud/composer.json +0 -5
- data/sdks/php-opencloud/scripts/bootstrap +0 -4
- data/sdks/php-opencloud/scripts/bootstrap.ps1 +0 -2
- data/sdks/php-opencloud/scripts/wrapper +0 -2
- data/sdks/php-opencloud/scripts/wrapper.ps1 +0 -1
- data/sdks/pkgcloud/.gitignore +0 -1
- data/sdks/pkgcloud/challenges/authenticate_token.js +0 -17
- data/sdks/pkgcloud/challenges/get_object_metadata.js +0 -18
- data/sdks/pkgcloud/scripts/bootstrap +0 -2
- data/sdks/pkgcloud/scripts/bootstrap.ps1 +0 -1
- data/sdks/pkgcloud/scripts/wrapper.ps1 +0 -1
- data/sdks/pyrax/.gitignore +0 -2
- data/sdks/pyrax/challenges/all_connections.py +0 -61
- data/sdks/pyrax/challenges/authenticate_token.py +0 -17
- data/sdks/pyrax/challenges/cdn_enable_container.py +0 -22
- data/sdks/pyrax/challenges/create_a_container.py +0 -21
- data/sdks/pyrax/challenges/create_server.py +0 -35
- data/sdks/pyrax/challenges/get_object_metadata.py +0 -17
- data/sdks/pyrax/challenges/upload_folder.py +0 -32
- data/sdks/pyrax/requirements.txt +0 -21
- data/sdks/pyrax/scripts/bootstrap +0 -9
- data/sdks/pyrax/scripts/bootstrap.ps1 +0 -7
- data/sdks/pyrax/scripts/wrapper +0 -3
- data/sdks/pyrax/scripts/wrapper.ps1 +0 -2
- data/spec/polytrix/challenge_builder_spec.rb +0 -16
- data/spec/rspec_spec.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c91cf7e97c088e23aa0134c2e20acfab0640195
|
4
|
+
data.tar.gz: 9bd8c63ae3cfbbc3bc75fc54c3b094ad848dd8c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5361e579064d58b4168e5929f995d1a42506c2faa49b246ddccd83eec3f2adef3d28b2761ab0bfd9b173e6ef690702b7eba56caef2e1a75746045c48c29e97b3
|
7
|
+
data.tar.gz: 61bcc9b099b67a95695cc59ac0d23baf3791cb8eec7c1bed382964c25e03ebc18fac01e6bce5bed6be1666e45a58ada4ef611323121dcf1bdc5c43c3c4f6823c
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
@@ -1,11 +1,6 @@
|
|
1
|
-
-
|
2
|
-
--format MatrixFormatter::Formatters::JSONFormatter
|
3
|
-
--out reports/matrix<%= ENV['TEST_ENV_NUMBER'].to_i %>.json
|
4
|
-
--format MatrixFormatter::Formatters::HTMLFormatter
|
5
|
-
--out reports/matrix.html
|
1
|
+
-r spec_helper
|
6
2
|
--format html
|
7
3
|
--out reports/rspec.html
|
8
4
|
--format documentation
|
9
5
|
--color
|
10
|
-
--require features_helper.rb
|
11
6
|
|
data/.rubocop-todo.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2014-06-12 15:05:43 -0400 using RuboCop version 0.18.1.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offences are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offence count: 41
|
9
|
+
Documentation:
|
10
|
+
Enabled: false
|
11
|
+
|
12
|
+
# Offence count: 57
|
13
|
+
LineLength:
|
14
|
+
Max: 165
|
15
|
+
|
16
|
+
# Offence count: 6
|
17
|
+
# Configuration parameters: CountComments.
|
18
|
+
MethodLength:
|
19
|
+
Max: 21
|
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -2,22 +2,6 @@
|
|
2
2
|
source "https://rubygems.org"
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
gem "pacto", :git => 'https://github.com/thoughtworks/pacto', :branch => 'uri_templates'
|
6
|
-
# uriTemplate support merged into webmock but not yet released - webmock#334
|
7
|
-
gem "webmock", :git => 'https://github.com/bblimke/webmock', :branch => 'master'
|
8
|
-
# optional param fix merged but not yet released - addressable#140
|
9
|
-
gem "addressable", :git => 'https://github.com/sporkmonger/addressable.git', :branch => 'master'
|
10
|
-
gem "fog", '~> 1.19'
|
11
|
-
gem "vcr"
|
12
|
-
gem "goliath"
|
13
|
-
gem "excon"
|
14
|
-
gem "em-http-request"
|
15
|
-
gem "rspec_junit_formatter"
|
16
5
|
gem "pry"
|
17
|
-
gem "matrix_formatter", :git => 'https://github.com/maxlinc/matrix_formatter', :branch => 'html5'
|
18
|
-
gem "highline"
|
19
|
-
gem "parallel_tests"
|
20
6
|
gem "rake-notes"
|
21
7
|
gem "simplecov"
|
22
|
-
gem "mixlib-shellout"
|
23
|
-
|
data/README.md
CHANGED
@@ -1,48 +1,139 @@
|
|
1
|
-
#
|
1
|
+
# Polytrix - the Polyglot Testing Matrix
|
2
2
|
|
3
|
-
|
4
|
-
- Lots of dependencies installed on your laptop
|
5
|
-
- VirtualBox & Vagrant, so you can install the necessary dependencies inside a local VM
|
6
|
-
- Packer and Vagrant-Rackspace, so you can build images and use images on the Rackspace cloud to run tests
|
3
|
+
Polytrix is a polyglot test runner and documentation generator. It aims to let you run sample code written in any language. It's especially useful if you want to run similar code samples in multiple languages. Simply put, if a project like [Slate](https://github.com/tripit/slate) looks like an interesting documentation option, then you might be interested in Polytrix for testing.
|
7
4
|
|
8
|
-
|
5
|
+
# Features
|
9
6
|
|
10
|
-
|
7
|
+
Polytrix samples defined in a "test manifest" written in YAML. The test manifest is meant to be portable so you can use you can create a "lightweight sample runner" in your preferred build/test tool of choice for your language, and then integrate the samples with Polytrix later to get the extra features. Polytrix can:
|
8
|
+
- Run sample code in any language and several platforms
|
9
|
+
- Perform compatibility testing checking multiple implementations (in different langauges) against the same set of assertions
|
10
|
+
- Generate documentation from sample code and test results
|
11
|
+
- Generate compatibility or feature matrix reports
|
11
12
|
|
12
|
-
|
13
|
+
Polytrix provides a few built-in assertions, but also has a plugin system that you can use to do more advanced validation, like using [Pacto](https://github.com/thoughtworks/pacto) to intercept and validate the usage of RESTful services.
|
13
14
|
|
14
|
-
|
15
|
+
# Usage preview
|
15
16
|
|
16
|
-
|
17
|
+
Polytrix is currently run via rspec. You can create a script that looks like this and run it with rspec:
|
17
18
|
|
18
|
-
|
19
|
+
```ruby
|
20
|
+
require 'polytrix/rspec'
|
19
21
|
|
20
|
-
|
22
|
+
Polytrix.implementors = Dir['sdks/*'].map{ |sdk|
|
23
|
+
name = File.basename(sdk)
|
24
|
+
Polytrix::Implementor.new :name => name
|
25
|
+
}
|
21
26
|
|
22
|
-
|
27
|
+
Polytrix.load_manifest 'polytrix_tests.yml'
|
28
|
+
Polytrix.bootstrap
|
29
|
+
Polytrix.run_tests
|
30
|
+
```
|
31
|
+
|
32
|
+
Polytrix will use the information in the Manifest and Implementors (see the sections below) to build an rspec test suite. It will setup tags for each Implementor, and names corresponding with the tests in the manifest.
|
33
|
+
|
34
|
+
So in our Polytrix examples project you can use commands like:
|
35
|
+
|
36
|
+
```sh
|
37
|
+
$ # Only run tests for the Java implementor
|
38
|
+
$ bundle exec rspec -t java
|
39
|
+
$ # Run the "hello world" tests in each language
|
40
|
+
$ bundle exec rspec -e "hello world"
|
41
|
+
```
|
42
|
+
|
43
|
+
## Usage Breakdown
|
44
|
+
|
45
|
+
### Defining Implementors (SDKs)
|
46
|
+
|
47
|
+
Polytrix can run the tests against multiple implementors. This usually means an SDK, but we used the generic term implementor because Polytrix works equally well for testing code katas, coursework, or other items. Perhaps even things like multi-platform plugins for [Calatrava](https://github.com/calatrava/calatrava/wiki/Plugins) or [PhoneGap](http://docs.phonegap.com/en/3.4.0/guide_hybrid_plugins_index.md.html#Plugin%20Development%20Guide).
|
48
|
+
|
49
|
+
This snippet defines the implementors:
|
50
|
+
```ruby
|
51
|
+
Polytrix.implementors = Dir['sdks/*'].map{ |sdk|
|
52
|
+
name = File.basename(sdk)
|
53
|
+
Polytrix::Implementor.new :name => name
|
54
|
+
}
|
55
|
+
```
|
56
|
+
|
57
|
+
See the full Implementor documentation for details on other attributes you can set, like `:language`. Polytrix will try to infer any information you don't pass.
|
58
|
+
|
59
|
+
#### Bootstrapping, compiling, wrapper scripts
|
23
60
|
|
61
|
+
Polytrix currently uses the [script/bootstrap](http://wynnnetherland.com/linked/2013012801/bootstrapping-consistency) pattern to allow each implementor to hook into dependency management, build tools, or other systems. Polytrix will look for three scripts (on Windows it will look for a *.ps1 version written in PowerShell):
|
62
|
+
|
63
|
+
| File | Purpose |
|
64
|
+
| ---------------- | -------------------------------------------------------------- |
|
65
|
+
| script/bootstrap | Prepare the SDK, usually by running depenency management tool. |
|
66
|
+
| script/wrapper | Wrapper script instead of executing code samples as scripts |
|
67
|
+
|
68
|
+
The bootstrap script is called by `Polytrix.bootstrap`. The wrapper script, if it exists, wraps the executino of the code sample. If there is no wrapper script, Polytrix will try to execute the sample code as a script. That works for many non-compiled scripting languages, like Ruby or Python, but won't work for something like Java.
|
69
|
+
|
70
|
+
If there is a wrapper script, Polytrix will call it with teh sample source file as the first argument, e.g.:
|
71
|
+
```sh
|
72
|
+
$ cd my_java_sdk
|
73
|
+
$ ./script/wrapper src/samples/HelloWorld.java
|
24
74
|
```
|
25
|
-
|
26
|
-
|
75
|
+
|
76
|
+
### Defining tests - the test manifest
|
77
|
+
|
78
|
+
Tests are defined in a YAML "test manifest" which defines what sample code should be executed, and what input it should receive. Standardizing the input is important for compliance testing, becaues it is difficult to maintain tests where one example expects "FOO=bar" and another expects "--foo bar".
|
79
|
+
|
80
|
+
A simple test manifest looks like this:
|
81
|
+
```yaml
|
82
|
+
---
|
83
|
+
global_env: # global_env defines input available for all scenarios
|
84
|
+
LOCALE: <%= ENV['LANG'] %> # templating is allowed
|
85
|
+
FAVORITE_NUMBER: 5
|
86
|
+
suites: # suites defines the test suites that can be executed
|
87
|
+
Katas: # "Katas" is the name of the first suite
|
88
|
+
env: # These "env" values are only available within the "Katas" suite
|
89
|
+
NAME: 'Max'
|
90
|
+
samples: # samples defines the individual tests in a suite
|
91
|
+
- hello world
|
92
|
+
- quine
|
93
|
+
Tutorials: # "Tutorials" is the name of the second suite
|
94
|
+
env:
|
95
|
+
samples:
|
96
|
+
- deploying
|
97
|
+
- documenting
|
27
98
|
```
|
28
99
|
|
29
|
-
###
|
100
|
+
### Test setup
|
101
|
+
|
102
|
+
`Polytrix.run_tests` runs the tests. Actually, right now it really just defines them in rspec, you still need to run the whole script via the RSpec command for the tests to run.
|
103
|
+
|
104
|
+
### Finding samples
|
105
|
+
|
106
|
+
Polytrix finds samples based on a loose naming convention. This makes it easier to use file names that are idiomatic for each implementor, while still allowing Polytrix to find the right file.
|
107
|
+
|
108
|
+
Polytrix basically does a case-insensitive search for a file whose name matches the scenario name, ignoring subfolders, spaces, prefixes, puctuation and file extension. So these files all match a scenario named "hello world":
|
109
|
+
- hello_world.rb
|
110
|
+
- src/com/world/HelloWorld.java
|
111
|
+
- samples/01_hello_world.go
|
112
|
+
|
113
|
+
### Reports and documentation
|
114
|
+
|
115
|
+
You can use any RSpec formatter with Polytrix, since Polytrix is based on RSpec.
|
116
|
+
|
117
|
+
There are also some Polytrix specific documentation and report generators. You can generate:
|
118
|
+
- Scenario-level reports: Documentation or reports for a single scenario
|
119
|
+
- Global reports: Documentation or reports summarizing all tested scenarios
|
120
|
+
|
121
|
+
The documentatio/reports are generated via a template processing system. Polytrix searches the template directory ('doc-src/' by default) for scenario-level samples using the same logic as in the "Finding samples" section above. It looks for a template matching "index" (e.g. index.md, index.rst, index.html) for the global report.
|
30
122
|
|
31
|
-
|
123
|
+
The templates are processed as ERB. In addition to being able to access the top-level Polytrix API, the following variables are bound:
|
124
|
+
| Variable | Description |
|
125
|
+
| ---------- | ---------------------------------------- |
|
126
|
+
| scenario | The name of the scenario being processed |
|
127
|
+
| challenges | One or more Challenge objects containing the scenario configuration and results |
|
32
128
|
|
33
|
-
|
34
|
-
* Run `vagrant up`, `vagrant provision`, and then `vagrant package --output drg.box`. These steps will take a while.
|
35
|
-
* Run `vagrant box add drg drg.box`
|
36
|
-
* You now have a drg box, and can restore the Vagrant file to it's original state.
|
129
|
+
### Common compliance tests
|
37
130
|
|
38
|
-
|
131
|
+
Refactoring... documentation coming soon.
|
39
132
|
|
133
|
+
### Plugins
|
40
134
|
|
135
|
+
Refactoring... documentation coming soon.
|
41
136
|
|
42
|
-
|
43
|
-
* Use standard, shared images (travis-images? vagrantcloud?)
|
44
|
-
* Integrate with travis-build for .travis.yml support
|
45
|
-
* Separate Polytrix framework from reference tests
|
137
|
+
# Influences
|
46
138
|
|
47
|
-
|
48
|
-
* Run tests as an interactive course via a browser
|
139
|
+
Several projects have influenced ideas in Polytrix. If you find Polytrix interesting or want to contribute, you may want to look at those projects. See influence.md.
|
data/Rakefile
CHANGED
@@ -1,30 +1,19 @@
|
|
1
1
|
require 'polytrix'
|
2
2
|
require 'bundler/gem_tasks'
|
3
|
-
require 'rspec/core/rake_task'
|
4
|
-
require 'pacto/rake_task'
|
5
3
|
require 'rake/notes/rake_task'
|
6
|
-
require '
|
7
|
-
require '
|
8
|
-
|
9
|
-
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'cucumber'
|
6
|
+
require 'cucumber/rake/task'
|
7
|
+
require 'rubocop/rake_task'
|
10
8
|
|
11
|
-
|
12
|
-
t.rspec_opts = "-I features"
|
13
|
-
t.pattern = 'features/**/*_spec.rb'
|
14
|
-
end
|
9
|
+
task :default => [:spec, :features, :self, :rubocop]
|
15
10
|
|
16
11
|
RSpec::Core::RakeTask.new('spec') do |t|
|
17
12
|
t.rspec_opts = "-f documentation"
|
18
13
|
end
|
19
14
|
|
20
|
-
|
21
|
-
|
22
|
-
desc 'Run all the SDK tests'
|
23
|
-
task :features => [:check_setup]
|
24
|
-
|
25
|
-
desc 'Check pre-requisites'
|
26
|
-
task :check_setup do
|
27
|
-
fail NOT_SETUP unless ENV['RAX_USERNAME'] && ENV['RAX_API_KEY']
|
15
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
16
|
+
t.cucumber_opts = "features --require features/support --require features/step_definitions"
|
28
17
|
end
|
29
18
|
|
30
19
|
desc 'Remove reports and other generated artifacts'
|
@@ -33,111 +22,17 @@ task :clean do
|
|
33
22
|
FileUtils.rm_rf 'reports'
|
34
23
|
end
|
35
24
|
|
36
|
-
desc '
|
37
|
-
task :
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
system "scripts/bootstrap"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
desc 'Configure the test framework'
|
52
|
-
task :setup do
|
53
|
-
username = ask "Enter your Rackspace Username: "
|
54
|
-
api_key = ask("Enter your Rackspace API KEY: "){|q| q.echo = "*"}
|
55
|
-
password = ask("Enter your Rackspace Password (for Packer): "){|q| q.echo = "*"}
|
56
|
-
|
57
|
-
puts "Creating .rbenv-vars"
|
58
|
-
File.open(".rbenv-vars", 'w') do |f|
|
59
|
-
f.puts "RAX_USERNAME=#{username}"
|
60
|
-
f.puts "RAX_API_KEY=#{api_key}"
|
61
|
-
f.puts
|
62
|
-
end
|
63
|
-
|
64
|
-
puts "Creating .packer-creds.json"
|
65
|
-
packer_creds = {
|
66
|
-
"RAX_USERNAME" => username,
|
67
|
-
"RAX_PASSWORD" => password
|
68
|
-
}
|
69
|
-
File.open(".packer-creds.json", "w") do |f|
|
70
|
-
f.puts JSON.pretty_generate packer_creds
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
namespace :documentation do
|
75
|
-
desc 'Generate annoted source code'
|
76
|
-
task :annotated do
|
77
|
-
system "groc"
|
78
|
-
end
|
79
|
-
|
80
|
-
task :copy_src do
|
81
|
-
sdks = Dir['sdks/*'].each do |sdk|
|
82
|
-
sdk = File.basename sdk
|
83
|
-
FileUtils.mkdir_p "docs/src/#{sdk}"
|
84
|
-
FileUtils.cp_r "sdks/#{sdk}/challenges/", "docs/src/#{sdk}"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
desc 'Generate the Feature Matrix dashboard'
|
89
|
-
task :dashboard => [:copy_src, :annotated] do
|
90
|
-
$: << 'features'
|
91
|
-
require 'features_helper'
|
92
|
-
require "matrix_formatter/assets/generator"
|
93
|
-
require "matrix_formatter/formatters/html5_report_writer"
|
94
|
-
require 'fileutils'
|
95
|
-
|
96
|
-
asset_generator_options = {
|
97
|
-
:extra_resource_paths => ['lib/formatter/resources']
|
98
|
-
}
|
99
|
-
asset_generator = MatrixFormatter::Assets::Generator.new asset_generator_options
|
100
|
-
asset_generator.generate
|
101
|
-
|
102
|
-
output = File.open("docs/dashboard.html", 'w')
|
103
|
-
options = {:view => 'angular.html.slim', :layout => 'default_layout.html.slim'}
|
104
|
-
formatter = MatrixFormatter::Formatters::HTML5ReportWriter.new output, options
|
105
|
-
matrix = formatter.parse_results Dir['reports/matrix*.json']
|
106
|
-
# puts MultiJson.encode formatter.matrix
|
107
|
-
formatter.write_report
|
108
|
-
output.close
|
109
|
-
|
110
|
-
fail "Combined results contain failures - check the reports" if formatter.has_failures?
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
desc "Run the tests in parallel, split by SDK. Doesn't work on Windows, but you can use rspec_parallel to split by file instead."
|
115
|
-
task :parallel_spec do
|
116
|
-
tags = Dir['sdks/*'].map{|sdk| File.basename sdk}
|
117
|
-
puts "Detected SDKs: #{tags}"
|
118
|
-
threads = []
|
119
|
-
Thread.main[:results] = []
|
120
|
-
tags.each_with_index do | tag, index |
|
121
|
-
threads << Thread.new do
|
122
|
-
puts "Starting #{tag} on process #{index}"
|
123
|
-
Thread.main[:results] << {
|
124
|
-
:tag => tag,
|
125
|
-
:success => sh("TEST_ENV_NUMBER=#{index} bundle exec rspec --options .rspec_parallel -t #{tag} features")
|
126
|
-
}
|
127
|
-
end
|
128
|
-
end
|
129
|
-
threads.each do |thread|
|
130
|
-
thread.join
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
namespace :image do
|
135
|
-
desc 'Build a Rackspace image (using Packer)'
|
136
|
-
task :rackspace do
|
137
|
-
system "cd packer; packer build -var-file=../.packer-creds.json -only openstack packer.json"
|
138
|
-
end
|
25
|
+
desc 'Self-test and self-document'
|
26
|
+
task :self do
|
27
|
+
sh 'bundle exec polytrix bootstrap'
|
28
|
+
sh 'bundle exec polytrix test'
|
29
|
+
sh 'bundle exec polytrix code2doc samples/sdks/java/challenges/*.java --target-dir=docs/samples/code2doc/java'
|
30
|
+
sh 'bundle exec polytrix code2doc samples/sdks/python/challenges/*.py --target-dir=docs/samples/code2doc/python'
|
31
|
+
sh 'bundle exec polytrix code2doc samples/sdks/ruby/challenges/*.rb --target-dir=docs/samples/code2doc/ruby'
|
32
|
+
# sh 'bundle exec polytrix code2doc samples/*.rb'
|
139
33
|
end
|
140
34
|
|
141
|
-
|
142
|
-
|
35
|
+
Rubocop::RakeTask.new(:rubocop) do |task|
|
36
|
+
# abort rake on failure
|
37
|
+
task.fail_on_error = true
|
143
38
|
end
|
data/bin/polytrix
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
This code will cause Polytrix to bootstrap:
|
2
|
+
|
3
|
+
<% challenges.compact.each do |challenge| %>
|
4
|
+
``` <%= challenge.implementor.language %>
|
5
|
+
<%= File.read(challenge.source_file) %>
|
6
|
+
```
|
7
|
+
|
8
|
+
And the results will look like:
|
9
|
+
```
|
10
|
+
<%= challenge.result.execution_result.stdout %>
|
11
|
+
```
|
12
|
+
|
13
|
+
<% end %>
|
data/docs/influences.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Influences
|
2
|
+
|
3
|
+
This project was influenced by many other projects. The following projects are worth checking out, either as alternatives you might want to use instead of Polytrix, or to understand the domain better before contributing.
|
4
|
+
|
5
|
+
# Polyglot Testing
|
6
|
+
|
7
|
+
## Travis-CI
|
8
|
+
|
9
|
+
I do not know of any project that is as far along as Travis in terms of making it easy to test projects in most common languages. Currently this project is inspired by Travis, but in the future I hope to re-use Travis components and contribute back to the Travis community.
|
10
|
+
|
11
|
+
The most important Travis components for Polyglot testing are:
|
12
|
+
- [travis-cookbooks](https://github.com/travis-ci/travis-cookbooks) and [travis-images](https://github.com/travis-ci/travis-images) - create environments that are setup for testing any popular language
|
13
|
+
- [https://github.com/travis-ci/travis-build](travis-build) - creates scripts that handle setting up the environment for a given platform (Linux, OSX, Windows) and follow language conventions for dependency management and compilation.
|
14
|
+
|
15
|
+
## JSON-LD Test Suite and EARL Report
|
16
|
+
|
17
|
+
I've seen several compliance test suites, but the [JSON-LD suite](http://json-ld.org/test-suite/) is one of my favorites, including the [earl-report](https://github.com/gkellogg/earl-report) gem it uses to create reports.
|
18
|
+
|
19
|
+
The main difference between Polytrix and JSON-LD's test suite (and similar compliance tests for other projects) is that JSON-LD is data-driven and Polytrix is driven by sample code. The JSON-LD approach is good for standards about a data format like JSON-LD, while Polytrix is more for testing the functional completeness of similar SDKs.
|
20
|
+
|
21
|
+
## Codecademy
|
22
|
+
|
23
|
+
Codecademy's [Course Creation](http://www.codecademy.com/docs/creation) documentation explains how they test code samples written in different languages. You can think of Polytrix as serving a similar function to Codecademy's [Submission Tests](http://www.codecademy.com/docs/submission_tests), with two important differences:
|
24
|
+
|
25
|
+
- Polytrix aims for a single submission test for all languages: so could share a "Hello, world!" submission correctness test for Ruby, Java, and PHP.
|
26
|
+
- Polytrix is being used for automated test suites where the code submissions are pre-written and repeatedly tested, though creating a course with Polytrix may be possible.
|
27
|
+
|
28
|
+
This of course has some limitations. Since Polytrix is polyglot, we generally test only the effect of running the sample and not the syntax. Polytrix is not suitable for testing each variation when [there's more than one way to do it](http://en.wikipedia.org/wiki/There's_more_than_one_way_to_do_it), but you can use it to test that at least one way is possible.
|
@@ -0,0 +1,13 @@
|
|
1
|
+
This is an example of the standard [Hello World](http://en.wikipedia.org/wiki/Hello_world_program)
|
2
|
+
program written in [Java][java].
|
3
|
+
```java
|
4
|
+
public class HelloWorld {
|
5
|
+
```
|
6
|
+
A Java CLI application is defined by creating a main method with this signature:
|
7
|
+
```java
|
8
|
+
public static void main(String[] args) {
|
9
|
+
System.out.println("Hello, world!");
|
10
|
+
}
|
11
|
+
}
|
12
|
+
```
|
13
|
+
[java]: http://en.wikipedia.org/wiki/Java_(programming_language)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
```java
|
2
|
+
public class Quine
|
3
|
+
{
|
4
|
+
public static void main(String[] args)
|
5
|
+
{
|
6
|
+
char q = 34; // Quotation mark character
|
7
|
+
String[] l = { // Array of source code
|
8
|
+
"public class Quine",
|
9
|
+
"{",
|
10
|
+
" public static void main(String[] args)",
|
11
|
+
" {",
|
12
|
+
" char q = 34; // Quotation mark character",
|
13
|
+
" String[] l = { // Array of source code",
|
14
|
+
" ",
|
15
|
+
" };",
|
16
|
+
" for(int i = 0; i < 6; i++ ) // Print opening code",
|
17
|
+
" System.out.println(l[i]);",
|
18
|
+
" for(int i = 0; i < l.length; i++) // Print string array",
|
19
|
+
" System.out.println( l[6] + q + l[i] + q + ',' );",
|
20
|
+
" for(int i = 7; i < l.length; i++) // Print this code",
|
21
|
+
" System.out.println( l[i] );",
|
22
|
+
" }",
|
23
|
+
"}",
|
24
|
+
};
|
25
|
+
for(int i = 0; i < 6; i++ ) // Print opening code
|
26
|
+
System.out.println(l[i]);
|
27
|
+
for(int i = 0; i < l.length; i++) // Print string array
|
28
|
+
System.out.println( l[6] + q + l[i] + q + ',' );
|
29
|
+
for(int i = 7; i < l.length; i++) // Print this code
|
30
|
+
System.out.println( l[i] );
|
31
|
+
}
|
32
|
+
}
|
33
|
+
```
|
@@ -0,0 +1,67 @@
|
|
1
|
+
Feature: Running SDKs
|
2
|
+
|
3
|
+
Polytrix uses the [script/bootstrap](http://wynnnetherland.com/linked/2013012801/bootstrapping-consistency) pattern to prepare SDKs for testing. You can hook into any package manager, compiler, build tool, or any other toolchain to prepare to build and run samples.
|
4
|
+
|
5
|
+
Polytrix also sets up tags for the SDKs so you can use the normal rspec `-t` option to select which SDK to run.
|
6
|
+
|
7
|
+
Scenario: Bootstrap an SDK
|
8
|
+
Given the java SDK
|
9
|
+
And the empty polytrix config
|
10
|
+
And the standard rspec setup
|
11
|
+
When I run `bundle exec rspec`
|
12
|
+
Then the output should contain ":compileJava"
|
13
|
+
And the output should contain "BUILD SUCCESSFUL"
|
14
|
+
|
15
|
+
Scenario: Running all SDKs
|
16
|
+
Given the ruby SDK
|
17
|
+
And the java SDK
|
18
|
+
And the python SDK
|
19
|
+
And the hello_world polytrix config
|
20
|
+
And the standard rspec setup
|
21
|
+
When I run `bundle exec rspec`
|
22
|
+
And the output should contain "3 examples, 0 failures"
|
23
|
+
|
24
|
+
Scenario: Running a single SDK
|
25
|
+
Given the ruby SDK
|
26
|
+
And the java SDK
|
27
|
+
And the python SDK
|
28
|
+
And the hello_world polytrix config
|
29
|
+
And the standard rspec setup
|
30
|
+
When I run `bundle exec rspec -t ruby`
|
31
|
+
Then the output should contain "Hello, world!"
|
32
|
+
And the output should contain "1 example, 0 failures"
|
33
|
+
|
34
|
+
Scenario: Custom assertions
|
35
|
+
Given the ruby SDK
|
36
|
+
And the java SDK
|
37
|
+
And the python SDK
|
38
|
+
And the hello_world polytrix config
|
39
|
+
And the standard rspec setup
|
40
|
+
And a file named "spec/custom_spec.rb" with:
|
41
|
+
"""
|
42
|
+
require 'polytrix/rspec'
|
43
|
+
|
44
|
+
Polytrix.configure do |polytrix|
|
45
|
+
Dir['sdks/*'].each do |sdk|
|
46
|
+
polytrix.implementor sdk
|
47
|
+
end
|
48
|
+
polytrix.test_manifest = 'polytrix_tests.yml'
|
49
|
+
end
|
50
|
+
|
51
|
+
# This is more of an integration test, but makes sure the rspec API is working.
|
52
|
+
# Expect results to all be pending, because there's no implementors in this proj.
|
53
|
+
|
54
|
+
Polytrix.validate(suite: 'Katas', sample: 'hello world') do |challenge|
|
55
|
+
# You can make assertions about the process using the Mixlib::ShellOut API
|
56
|
+
expect(challenge[:result].execution_result.stdout).to include 'Hello, world!'
|
57
|
+
expect(challenge[:result].execution_result.stderr).to be_empty
|
58
|
+
expect(challenge[:result].execution_result.exitstatus).to eq(1) # normally this would be 0
|
59
|
+
end
|
60
|
+
|
61
|
+
Polytrix.validate(suite: 'Katas', sample: 'quine') do |challenge|
|
62
|
+
expect(challenge[:result].execution_result.stdout).to eq File.read(challenge[:result].source)
|
63
|
+
end
|
64
|
+
Polytrix.load_tests
|
65
|
+
"""
|
66
|
+
When I run `bundle exec rspec spec/custom_spec.rb`
|
67
|
+
And the output should match /expected: 1\s+got: 0/
|