-
Snippets should use environmental variables to store user account information instead of placeholders. For example (in NodeJS):
accountSid = process.env.TWILIO_ACCOUNT_SIDInstead 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: CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXIn 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-javav7.x should be named as:snippet-example-1.7.x.javaThe 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.pyAnd 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.jsonClient 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
xmlresult to the standard output, so we can capture that output and compare it with the expectedxmlsample. We read this/output/sample.xmlfile 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.jsonfile: This file is required and must live in all snippet folders, inside you can enable its specific folder for testing, adding"testable": truelike so:{ "title": "Snippet title", "type": "server", "testable": true } -
Using a
test.ymlfile: 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: trueto the file like so:testable: true
Notes:
-
For testing TwiML snippets the option available is:
meta.json -> "test_output": true test.yml -> test_output: trueThis will compare the output of the snippet with the
output/sample.xmlfile 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: falseThis 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
mainmethod 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 nokogiriYou 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.rbNote: 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 -iNote: 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 [email protected]: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
keystoredirectory of the fake-api repo. Go here for more information.
-
Change your hosts file.
Edit your
/etc/hostsfile. 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.examplefile.cp .env.example .env
-
Set the necessary environment variables.
Change environment variables in the
.envfile to match your configuration and then use thesourcecommand 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.yamlfile. 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