-
Snippets should use environmental variables to store user account information instead of placeholders. For example (in NodeJS):
accountSid = process.env.TWILIO_ACCOUNT_SID
Instead of:
accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
As the latter impose a high security risk for users who push their own credentials on public repositories.
-
Critical user account information that should be stored on environmental variables is:
- Account SID
- Sub accounts SIDs
- Authentication Token
- API key SID
- API key Secret
Any other information such as Call SID, etc. can have placeholders on them:
Call SID: CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
In the case of phone numbers, the following should be used:
Destination Phone Number: +15558675310 From/Twilio Number: +15017122661
-
Snippet file names are important. A snippet's file extension is the only way to mark them for a specific language. This is important because the language will be visible on the docs. Also, you must mark snippets with the twilio-client version that is used in that particular snippet.
For example, a java snippet that uses
twilio-java
v7.x should be named as:snippet-example-1.7.x.java
The same applies to the rest of languages and library versions, and this is the list of currently supported languages and versions:
snippet-example-1.6.x.java snippet-example-1.7.x.java snippet-example-1.2.x.js snippet-example-1.3.x.js snippet-example-1.4.x.rb snippet-example-1.5.x.rb snippet-example-1.4.x.cs snippet-example-1.5.x.cs snippet-example-1.4.x.php snippet-example-1.5.x.php snippet-example-1.5.x.py snippet-example-1.6.x.py
And the full structure should look like this:
rest/ |-- resource-example/ └── snippet-example-1/ |-- output/ | └── snippet-example-1.json |-- snippet-example-1.7.x.java |-- snippet-example-1.<sdk-version>.x.<language> |-- snippet-example-1.json.curl |-- snippet-example-1.xml.curl └── meta.json
Client version is important, as that is how the test harness knows which version of the client it should use for testing.
All snippets are run in a container-based environment for each language (see .travis.yml file), so the first check we do is for syntax error.
There're two kind of snippets we test:
-
API/REST snippets: For these cases we only check syntax error. But, these snippets also do a request to Twilio's endpoints, so we mock this behaviour using a fake API server.
Note: The test doesn't check if the http request body is well formed to do what the intended snippet is supposed to do, e.g., if you have a snippet doing
resource.update(propA=True)
, but the expected result is to updatepropB
, the test may go green because there's no syntax error. That's because some attributes are optional to update, so the request body may or may not has the parameters needed to update the resource according to the expected result. -
TwiML snippets: When running TwiML snippets, the snippets should print the
xml
result to the standard output, so we can capture that output and compare it with the expectedxml
sample. We read this/output/sample.xml
file which is placed in the same folder of the snippet.
If you want a snippet folder to be tested, there are two ways to mark it as testable:
-
Using a
meta.json
file: This file is required and must live in all snippet folders, inside you can enable its specific folder for testing, adding"testable": true
like so:{ "title": "Snippet title", "type": "server", "testable": true }
-
Using a
test.yml
file: This file is optional and can live inside any folder, it's used to specify a deep recursive testing for all folders inside. So, if the marked directory contains several snippets, all of them will be marked as testable recursively. You just need to addtestable: true
to the file like so:testable: true
Notes:
-
For testing TwiML snippets the option available is:
meta.json -> "test_output": true test.yml -> test_output: true
This will compare the output of the snippet with the
output/sample.xml
file inside the same directory of the snippet. -
You can mark a directory or a snippet to be not testable too.
meta.json -> "testable": false test.yml -> testable: false
This way, you can mark snippets or directories to be tested or not, by exception.
-
For a snippet to be testable, it has to contain the basic things a program in that language should have. For example in Java, the code snippet should have a public class and a
main
method in it. -
Specific dependencies are supported for snippets. If a new dependency is introduced, the testing scripts should be modified to support it.
The next steps describe how to run the snippets test locally in a UNIX based operating system (examples will be provided for Debian based Linux distributions and OSX using Homebrew). This has not been tested in a Windows OS.
Make sure you have the following dependencies installed on your system.
-
Install Node.js. The best option for this is to use nvm
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.2/install.sh | bash \ export NVM_DIR="$HOME/.nvm" \ [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" \ nvm install --lts npm install
-
Install Python and PIP.
- On Linux:
sudo apt-get install python-pip python2.7-dev build-essential \ sudo pip install --upgrade pip
- On OSX:
brew install python
Once you have python and pip ready, run the command below
pip install -r requirements.txt
-
Install JDK8 and Gradle. The best option for this is to use sdkman
curl -s "https://get.sdkman.io" | bash \ source "$HOME/.sdkman/bin/sdkman-init.sh" \ sdk install java \ sdk install gradle
-
Install PHP 5 with CURL.
- On Linux:
sudo add-apt-repository ppa:ondrej/php -y sudo apt-get update sudo apt-get install -y --force-yes php5.6
- On OSX:
brew install php56
Once you have php ready, please install Composer
curl -sS https://getcomposer.org/installer | \ sudo php -- --install-dir=/usr/local/bin --filename=composer
-
Install Ruby and RubyGems.
curl -sSL https://get.rvm.io | bash -s stable --ruby
-
Install MonoDevelop.
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF \ echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list \ sudo apt-get update \ sudo apt-get install mono-complete -y
- On OSX:
brew install mono
The testing and installation scripts use ruby. Before installing language dependencies you need to install the following gems:
gem install json colorize nokogiri
You can use the following command to install language dependencies, which will download the latest version of the helper libraries for each language:
ruby tools/snippet-testing/model/dependency.rb
Note: That file specifies the latest version for every helper library for
each language, but for java the files to specify the versions are located in:
tools/snippet-testing/language_handler/file-templates/build.<version>.gradle
where <version>
should be 6
or 7
.
Another option is to use the snippet_tester.rb
file and pass the -i
flag,
this will try to install whatever dependency is needed before running the tests:
ruby tools/snippet-testing/snippet_tester.rb -i
Note: This will also install missing dependencies before running the tests.
sudo
will be used within the dependency installation script so you might need
to enter your password.
DO NOT run the whole script with sudo
as it would install dependencies for
the wrong user.
-
Clone and run the fake-api server in a different terminal session.
git clone git@github.com:TwilioDevEd/twilio-api-faker.git \ cd twilio-api-faker \ sudo gradle run
-
Make your system trust the fake server's self signed certificate.
- On Linux:
sudo apt-get install ca-certificates \ sudo cp twilio-api-faker/keystore/twilio_fake.pem /usr/local/share/ca-certificates/twilio_fake.crt \ sudo update-ca-certificates
- On OSX:
Use the system's keychain to trust the provided certificate in the
keystore
directory of the fake-api repo. Go here for more information.
-
Change your hosts file.
Edit your
/etc/hosts
file. Add the following entries:127.0.0.1 api.twilio.com 127.0.0.1 chat.twilio.com 127.0.0.1 fax.twilio.com 127.0.0.1 ip-messaging.twilio.com 127.0.0.1 lookups.twilio.com 127.0.0.1 messaging.twilio.com 127.0.0.1 monitor.twilio.com 127.0.0.1 notifications.twilio.com 127.0.0.1 notify.twilio.com 127.0.0.1 pricing.twilio.com 127.0.0.1 preview.twilio.com 127.0.0.1 sync.twilio.com 127.0.0.1 taskrouter.twilio.com 127.0.0.1 video.twilio.com 127.0.0.1 wireless.twilio.com
-
Make a copy of the
.env.example
file.cp .env.example .env
-
Set the necessary environment variables.
Change environment variables in the
.env
file to match your configuration and then use thesource
command to export the variables.source .env
-
Finally, run the tests.
ruby tools/snippet-testing/snippet_tester.rb
Note: Remember to mark the directories you want to be tested with a
test.yaml
file. For more information go here.You can also specify a directory to be tested (relative or absolute path). If a directory is specified, then the default testing behavior for that directory and everything it contains is
true
.ruby tools/snippet-testing/snippet_tester.rb -d rest/making-calls