GithubHelp home page GithubHelp logo

ts's Introduction

ts(1) -- test script

SYNOPSIS

ts [options] TEST_SCRIPT...

[./test_script] [options] TESTS...

DESCRIPTION

ts provides functions for writing tests in shell. The test scripts can be run individually or in a batch format using ts as a command.

ts makes a test directory available on a per-test basis so it's easy to sandbox tests that write or manipulate files. ts tries to use POSIX exclusively and so should (hopefully) work with any POSIX-compliant shell.

TEST SCRIPTS

The ts command expects script files that define test cases. Test scripts have the following form:

[./example]
#!/bin/sh
# pick a shell, any (POSIX) shell

setup () {              # optional setup
  mkdir -p "$ts_test_dir"
}

teardown () {           # optional teardown
  rm -r "$ts_test_dir"
}

test_true () {          # write tests named like "test_"
  true                  # return 0 to pass.
}

. ts                    # source ts to run the tests

To run, use any of:

ts example              # run multiple test scripts
./example               # run a single test script
./example test_a_thing  # run a single test

To debug, try using -e to execute the test function in isolation.

./example -e test_a_thing    # a most useful pattern

See the FUNCTIONS, EXAMPLES, and TROUBLESHOOT sections for more details.

OPTIONS

These options control how ts operates.

  • -a: Show passing outputs, which are normally filtered.

  • -c: Colorize output. (green/red/yellow - pass/fail/not-executable)

  • -d: Debug mode. Turns on xtrace (set -x) for the tests and enables -v.

  • -e: Exec mode. Runs a test without processing the output and exits.

  • -h: Prints help.

  • -m: Monitor output. Provide a ticker indicating the progress of tests and print a summary. Monitor is the default.

  • -q: Quiet output. Shows only stdout, hiding stderr.

  • -r: Remove the tmp dir on complete. Removal is done using rm -r.

  • -s: Stream output. Show test progress as it happens. No summary is printed.

  • -t: Set the test tmp dir (default tmp). The test-specific directories are be located under this directory.

  • -v: Verbose output. Display both stdout and stderr for the tests (enabled by default).

FUNCTIONS

Functions provided by ts.

  • setup:

    A setup function run before each test.

  • teardown:

    A teardown function run after each test.

    ts ensures teardown runs by setting a trap for EXIT signals during setup and the actual test. As a result, EXIT traps in tests can prevent teardown.

  • assert_status EXPECTED ACTUAL [MESSAGE]:

    Exit 1 unless the numbers EXPECTED and ACTUAL are the same. Use this to make assertions in the middle of a test.

  • assert_output EXPECTED ACTUAL:

    Return 1 unless the variables EXPECTED and ACTUAL are the same. Reads from stdin for '-'. Also reads ACTUAL from stdin if ACTUAL is unspecified.

    Using assert_output in a pipeline is often convenient but remember this assertion only returns, it does not exit. As a result you should either use it as the very last command in a test, or follow it with assert_status in a multipart test. See the section on my 'tests aren't failing' for more.

  • skip [MESSAGE]:

    Skip a test. Exits 0 but counts as a skip and not a pass.

ts reserves all function names starting with 'ts_' for internal use. Note that setup and teardown commands on PATH will be ignored because tests will shadow them with the corresponding ts functions.

VARIABLES

Variables provided by ts at runtime. Feel free to use any of them but treat them as read-only.

  • ts_test_file: The name of the current test script being run.

  • ts_test_case: The basename of the test file, minus the extname.

  • ts_test_lineno: The line number where the current test is defined.

  • ts_test_name: The name of the current test.

  • ts_test_dir: The test-specific directory.

    The test dir is 'tmp_dir/test_case'. ts does not create this directory automatically. Add that functionality in the setup function as needed.

ts reserves all variables starting with 'ts_' for internal use.

ENVIRONMENT

The behavior of ts can be modified via environment variables. Many of these may be set using options.

  • TS_USR_DIR (pwd): The user dir. Used to determine the ts tmp dir.

  • TS_TMP_DIR ($TS_USR_DIR/tmp): The base tmp dir.

  • TS_COLOR (false): Set to "true" to enable color.

  • TS_DIFF (diff): The diff command used by assert_output.

  • TS_DEBUG (false): Set to "true" to enable debug mode.

  • TS_REMOVE_TMP_DIR (false): Set to "true" to remove tmp dir.

In addition these variables adjust the color output.

  • TS_PASS (green): Passing tests.

  • TS_FAIL (red): Failing tests.

  • TS_SKIP (yellow): Skipped tests.

  • TS_NORM (normal): The normal output color.

For example to turn failures blue:

export TS_FAIL=$(printf "%b" "\033[0;34m")

ts reserves all variables starting with 'TS_' for internal use.

EXAMPLES

Basic usage:

[./example]
#!/bin/sh

test_arbitrary_function () {
  echo abc | grep -q b
}

test_assert_status () {
  false
  assert_status 1 $?
}

test_assert_output_style_one () {
  out=$(printf "hello world")
  assert_output "hello world" "$out"
}

test_assert_output_style_two () {
  printf "hello world" | assert_output "hello world"
}

test_assert_output_style_three () {
printf "hello world\n" | assert_output "\
hello world
"
}

test_skip_test () {
skip "skipping this one"
false
}

. ts

Run like:

chmod +x example
ts example

Shared examples:

[./common_tests]
test_it_should_pick_lines_with_abc () {
printf "%s\n" "1 abc" "2 xyz" "3 abc" |
${picker} | assert_output "\
1 abc
3 abc
"
}

[./test_grep_abc]
#!/bin/sh
picker="grep abc"
. ts . ./common_tests
. ts

[./test_sed_abc]
#!/bin/sh
picker="sed -ne /abc/p"
. ts . ./common_tests
. ts

Run like:

chmod +x test_grep_abc test_sed_abc
ts test_grep_abc test_sed_abc

Background jobs work fine, just be sure to cleanup:

[./background]
#!/bin/sh

teardown () {
  jobs -p | xargs kill -9
  true
}

test_background_job () {
  sleep 3 &
  true
}

. ts

TROUBLESHOOT

My tests aren't running

Be sure you added . ts at the end of your script.

My tests are failing

1) Are you incrementing a variable in a loop in a pipeline?

See http://mywiki.wooledge.org/BashFAQ/024.

2) Is a newline missing from a variable?

Subshells chomp the last newline off of a command.

test_newline_is_missing_so_this_fails () {
out=$(echo abc)

assert_output "\
abc
" "$out"
}

One way around this is to print a sacrificial non-newline character.

test_newline_is_now_accounted_for () {
out=$(echo abc; printf x)

assert_output "\
abc
" "${out%x}"
}

Another way is to pipe into assert_output.

test_another_newline_strategy () {
echo abc | assert_output "\
abc
"
}

My tests aren't failing

1) Are you using assert_output in a pipeline?

ts assert methods return failure (rather than exit) so this will pass.

test_multiple_asserts_not_failing_as_intended () {
  assert_output "1" "0"
  assert_output "0" "0"
}

The reason is that exit within a pipeline has shell-specific behavior. For instance if you run this with different values of shell you will get 0 for bash and dash, and 1 for zsh and ksh.

$shell <<DOC
yes | exit 1
exit 0
DOC
echo $?

As a result you cannot get consistent behavior if assert_output exits rather than returns; in bash/dash a failing assert_output in a pipeline would be ignored while in ksh/zsh it would be respected. So what do you do if you want multiple assertions?

One way is to && all the asserts at the end of the test.

test_this_fails_as_expected () {
  printf "0" | assert_output "1" &&
  assert_output "0" "0"
}

Another way is to use assert_status. Unlike assert_output, assert_status exits (it does not return). This is ok because there is no good reason to use assert status in a pipeline - the intent is to use it as a breakout from a multipart test. As a result you can use a message with assert_status to track progress.

test_this_also_fails_as_expected () {
  printf "0" | assert_output "1"
  assert_status "0" $? "checking the pipeline"
  assert_output "0" "0"
}

Teardown isn't running

Are you setting an EXIT trap? ts uses an EXIT trap to ensure that teardown runs even when setup or a test exits. Resetting an EXIT trap can prevent teardown from running.

test_teardown_will_not_run () {
  trap - EXIT
  exit 1
}

Run times are showing up as -1

Timing is driven by the SECONDS environment variable, which is not a part of the POSIX spec, and is not provided by all shells (ex DASH). When it is not present the timing shows up as -1 s.

The date command is specified by POSIX and could be a replacement for SECONDS, but the verb %s (seconds since epoch) is not a part of the spec. Doing the math on the POSIX verbs could work, but that solution has not been implemented yet.

I'm using DASH (maybe you're on ubuntu)

DASH is quirky. Last I checked you cannot concatenate options like you can in other shells, so when launching scripts individually (the only time this applies) you must separate options out.

./test_script -s -c  # this
./test_script -sc    # not this!

Shared examples do not work with DASH - the . ts . files... syntax relies on the dot operator to set arguments which dot in DASH does not do. There isn't actually anything in the POSIX spec that says it should, but it's a break in the conventions used by other shells.

I'm using BusyBox (maybe you're on alpine)

The diff in BusyBox only outputs unified format, which isn't what the POSIX spec asks for. That means parts of the ts test suite written to expect the default POSIX output cannot pass. These tests are skipped. This quirk of BusyBox should not affect your tests, but note the output of your tests may change a little when run vs BusyBox.

INSTALLATION

Add ts to your PATH (or execute it directly). A nice way of doing so is to clone the repo and add the bin dir to PATH. This allows easy updates via git pull and should make the manpages available via man ts.

git clone git://github.com/thinkerbot/ts.git
export PATH="$PATH:$(pwd)/ts/bin"

If you're using homebrew on OSX you can tap goodlittlescript.

brew tap goodlittlescript/homebrew-gls
brew install ts

DEVELOPMENT

Clone the repo as above. To run the tests (written in ts):

./test/suite

To run the tests on latest image/shell combinations, or a specific image/shell combination (requires docker):

# latest for several major distros
./Projectfile test-all

# pick a image/shell you specifically care about
./Projectfile test-os ubuntu:16.04 /bin/bash

To make a release:

./Projectfile prepare-release <version>

Report bugs here: http://github.com/thinkerbot/ts/issues.

CONTRIBUTORS

Thanks for the help!

  • Angelo Lakra (github.com/alakra)
  • Thomas Adam (github.com/ThomasAdam)
  • David Alfonso (github.com/davidag)

COPYRIGHT

TS is Copyright (C) 2011 Simon Chiang http://github.com/thinkerbot

ts's People

Contributors

davidag avatar thinkerbot avatar thomasadam 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

Watchers

 avatar  avatar  avatar  avatar

ts's Issues

Kill jobs on teardown

Probably need to think about this more, but if you start background jobs then they will hang without something like this:

  jobs -p | xargs kill

Bonus points to kill politely, then kill -9 if they don't exit in a reasonable time.

-t does not expand tmp dir

This can lead to some unexpected behavior because by default ts_tmp_dir is a full path. So expand the tmpdir when set.

Add note that test are run in same process group as ts

The result of which is that if you kill the process group within a test then you kill ts itself. This is hard to avoid because (AFAIK) setting the process group id requires system-specific things like setsid, or a programming language like ruby with Process.setsid, or maybe job control in bash. Moreover, you might want to keep it this way so that signals sent to the ts group will go to all ts tests... hard to say, good to make a note about.

ps -j -p $$
test_process_groups () {
  ps -j -p $$
  bash -c 'ps -j -p $$'
  false
}

-s perhaps should assume -a

Otherwise the passing tests are filtered so you get no feedback and you think it's just haning (exactly the opposite you'd expect with the streaming interface).

ts' code is almost unreadable in places (not "bash" like)

Some of the code in ts is rather awkward in that:

  • It's written in places in a very C-like way. See ts_format() for example where we have:

if [ true = "$TS_COLOR" ]

Which is written usually as:

if [ "$TS_COLOR" = "true" ]

Bash does not suffer from assignment problems like in C.

  • There's a mixture of different indentation levels (2 spaces, 4 spaces, etc), and in some cases not at all. The indentation style in ts_run_test_suite() is a good example of this.

I'm proposing a reindentation effort, and am happy to do this as an example, to show how things might be more bash-like (and hence readable).

Error on -r

/Users/simonchiang/.dotfiles/bin/ts: line 174: /Users/simonchiang/Documents/Repos/savepoint/tmp/status: No such file or directory

ts tests failing on clean repository with dash

In Debian testing/bullseye, clone the ts repository and run tests/suite as suggested in README:

~/projects/ts$ ./test/suite                                                                    
............F........................................F.....F.....F...

[./test/suite:201] test_ts_runs_cleanly_with_no_tests
  unequal output:
  3c3
  < 0 pass 0 fail 0 skip 0 s
  ---
  > 0 pass 0 fail 0 skip -1 s
F

[./test/suite:783] test_include
  unequal output:
  3c3
  < P [test/examples/include -> test/examples/include a:3] test_include_a
  ---
  > P [test/examples/include:3] test_include
  5,7c5
  < P [test/examples/include -> test/examples/include b:3] test_include_b
  <
  < P [test/examples/include -> test/examples/include b -> test/examples/include_c:3] test_include_c
  ---
  > P [test/examples/include:3] test_include
F

[./test/suite:816] test_undeclared_variable
  unequal output:
  2c2
  <   test/examples/undeclared_variable: line 8: var: unbound variable
  ---
  >   test/examples/undeclared_variable: 8: /home/david/projects/ts/bin/ts: var: parameter not set
F

[./test/suite:862] test_ts_readme_common_tests
  unequal output:
  1,4d0
  < P [./test_grep_abc -> ./common_tests:1] test_it_should_pick_lines_with_abc
  <
  < P [./test_sed_abc -> ./common_tests:1] test_it_should_pick_lines_with_abc
  <
F

65 pass 4 fail 0 skip -1 s

As already noted in the README, dash has some strange behaviors but I wonder if ts own tests should pass on it, being the default sh shell in Debian/Ubuntu distributions.

Error when calculating timing in ksh

I've observed the following:

./Projectfile shell centos
/bin/ksh
ln -sf /bin/ksh /bin/sh
./test/pass
# .
# 
# ./test/pass[8]: .: line 269: 0.092 - 0.041: arithmetic syntax error

The root cause appears to be ksh being unable to handle floating point math, which occurs when calculating run time https://github.com/thinkerbot/ts/blob/master/bin/ts#L269

# echo $((1 + 2))
3
# echo $((1.1 + 2.2))
/bin/ksh: 1.1 + 2.2: arithmetic syntax error

Possibly use bc instead of shell math.

tr -u unavailable on ubuntu

This buggers the monitor output. It's difficult to find a way to unbuffer the output in a POSIX way -- indeed there may be none. Other options include using awk, or use tricks to remove the newline in sed. In both cases there isn't a POSIX-specified option for fflush (awk) or -l in sed.

Add assert_script method

Implement in the back-end using expect. Pass if the whole thing passes. See thinkerbot/shell_test for guidance.

Bakefile tests failing on clean repository

In Debian testing/bullseye, clone the ts repository and run ./Bakefile test-all as suggested in the README:

~/projects/ts$ ./Bakefile test-all
# alpine /bin/bash      69 pass 0 fail 0 skip 1 s
# alpine /bin/zsh       65 pass 4 fail 0 skip 4 s
F alpine /bin/zsh       [./test/suite:213] test_ts_accepts_options_anywhere
F alpine /bin/zsh       [./test/suite:223] test_script_accepts_options_anywhere
F alpine /bin/zsh       [./test/suite:778] test_ts_options
F alpine /bin/zsh       [./test/suite:816] test_undeclared_variable
# centos /bin/bash      69 pass 0 fail 0 skip 2 s
# centos /bin/zsh       64 pass 5 fail 0 skip 5 s
F centos /bin/zsh       [./test/suite:213] test_ts_accepts_options_anywhere
F centos /bin/zsh       [./test/suite:223] test_script_accepts_options_anywhere
F centos /bin/zsh       [./test/suite:778] test_ts_options
F centos /bin/zsh       [./test/suite:816] test_undeclared_variable
F centos /bin/zsh       [./test/suite:829] test_ts_allows_exit_trap
# centos /bin/ksh       68 pass 1 fail 0 skip 1 s
F centos /bin/ksh       [./test/suite:816] test_undeclared_variable
# debian /bin/bash      69 pass 0 fail 0 skip 5 s
# debian /bin/zsh       65 pass 4 fail 0 skip 4 s
F debian /bin/zsh       [./test/suite:213] test_ts_accepts_options_anywhere
F debian /bin/zsh       [./test/suite:223] test_script_accepts_options_anywhere
F debian /bin/zsh       [./test/suite:778] test_ts_options
F debian /bin/zsh       [./test/suite:816] test_undeclared_variable
# debian /bin/ksh       67 pass 2 fail 0 skip 1 s
F debian /bin/ksh       [./test/suite:709] test_ts_uses_TS_DIFF_to_diff_outputs
F debian /bin/ksh       [./test/suite:816] test_undeclared_variable
# fedora /bin/bash      50 pass 0 fail 19 skip 1 s
S fedora /bin/bash      [./test/suite:416] test_script_e_option_executes_test_in_shell
S fedora /bin/bash      [./test/suite:709] test_ts_uses_TS_DIFF_to_diff_outputs
S fedora /bin/bash      [./test/suite:754] test_ts_returns_to_TS_USR_DIR_for_each_test
S fedora /bin/bash      [./test/suite:758] test_ts_exit_fail_in_setup
S fedora /bin/bash      [./test/suite:762] test_ts_exit_fail_in_test
S fedora /bin/bash      [./test/suite:766] test_ts_exit_fail_in_teardown
S fedora /bin/bash      [./test/suite:770] test_ts_exit_fail_after_untrap_EXIT
S fedora /bin/bash      [./test/suite:774] test_ts_fail_examples
S fedora /bin/bash      [./test/suite:778] test_ts_options
S fedora /bin/bash      [./test/suite:796] test_ts_pass_examples
S fedora /bin/bash      [./test/suite:800] test_ts_public_function_conflict
S fedora /bin/bash      [./test/suite:804] test_ts_return_fail_in_setup
S fedora /bin/bash      [./test/suite:808] test_ts_return_fail_in_teardown
S fedora /bin/bash      [./test/suite:812] test_ts_test_detection
S fedora /bin/bash      [./test/suite:816] test_undeclared_variable
S fedora /bin/bash      [./test/suite:853] test_ts_background_job_example
S fedora /bin/bash      [./test/suite:858] test_ts_readme_example
S fedora /bin/bash      [./test/suite:872] test_ts_readme_troubleshoot_fail
S fedora /bin/bash      [./test/suite:876] test_ts_readme_troubleshoot_pass
# fedora /bin/zsh       48 pass 2 fail 19 skip 1 s
F fedora /bin/zsh       [./test/suite:213] test_ts_accepts_options_anywhere
F fedora /bin/zsh       [./test/suite:223] test_script_accepts_options_anywhere
S fedora /bin/zsh       [./test/suite:416] test_script_e_option_executes_test_in_shell
S fedora /bin/zsh       [./test/suite:709] test_ts_uses_TS_DIFF_to_diff_outputs
S fedora /bin/zsh       [./test/suite:754] test_ts_returns_to_TS_USR_DIR_for_each_test
S fedora /bin/zsh       [./test/suite:758] test_ts_exit_fail_in_setup
S fedora /bin/zsh       [./test/suite:762] test_ts_exit_fail_in_test
S fedora /bin/zsh       [./test/suite:766] test_ts_exit_fail_in_teardown
S fedora /bin/zsh       [./test/suite:770] test_ts_exit_fail_after_untrap_EXIT
S fedora /bin/zsh       [./test/suite:774] test_ts_fail_examples
S fedora /bin/zsh       [./test/suite:778] test_ts_options
S fedora /bin/zsh       [./test/suite:778] test_ts_options
S fedora /bin/zsh       [./test/suite:796] test_ts_pass_examples
S fedora /bin/zsh       [./test/suite:800] test_ts_public_function_conflict
S fedora /bin/zsh       [./test/suite:804] test_ts_return_fail_in_setup
S fedora /bin/zsh       [./test/suite:808] test_ts_return_fail_in_teardown
S fedora /bin/zsh       [./test/suite:812] test_ts_test_detection
S fedora /bin/zsh       [./test/suite:816] test_undeclared_variable
S fedora /bin/zsh       [./test/suite:853] test_ts_background_job_example
S fedora /bin/zsh       [./test/suite:858] test_ts_readme_example
S fedora /bin/zsh       [./test/suite:872] test_ts_readme_troubleshoot_fail
S fedora /bin/zsh       [./test/suite:876] test_ts_readme_troubleshoot_pass
# fedora /bin/ksh       50 pass 0 fail 19 skip 1 s
S fedora /bin/ksh       [./test/suite:416] test_script_e_option_executes_test_in_shell
S fedora /bin/ksh       [./test/suite:709] test_ts_uses_TS_DIFF_to_diff_outputs
S fedora /bin/ksh       [./test/suite:754] test_ts_returns_to_TS_USR_DIR_for_each_test
S fedora /bin/ksh       [./test/suite:758] test_ts_exit_fail_in_setup
S fedora /bin/ksh       [./test/suite:762] test_ts_exit_fail_in_test
S fedora /bin/ksh       [./test/suite:766] test_ts_exit_fail_in_teardown
S fedora /bin/ksh       [./test/suite:770] test_ts_exit_fail_after_untrap_EXIT
S fedora /bin/ksh       [./test/suite:774] test_ts_fail_examples
S fedora /bin/ksh       [./test/suite:778] test_ts_options
S fedora /bin/ksh       [./test/suite:796] test_ts_pass_examples
S fedora /bin/ksh       [./test/suite:800] test_ts_public_function_conflict
S fedora /bin/ksh       [./test/suite:804] test_ts_return_fail_in_setup
S fedora /bin/ksh       [./test/suite:808] test_ts_return_fail_in_teardown
S fedora /bin/ksh       [./test/suite:812] test_ts_test_detection
S fedora /bin/ksh       [./test/suite:816] test_undeclared_variable
S fedora /bin/ksh       [./test/suite:853] test_ts_background_job_example
S fedora /bin/ksh       [./test/suite:858] test_ts_readme_example
S fedora /bin/ksh       [./test/suite:872] test_ts_readme_troubleshoot_fail
S fedora /bin/ksh       [./test/suite:876] test_ts_readme_troubleshoot_pass
# opensuse /bin/bash    69 pass 0 fail 0 skip 1 s
# opensuse /bin/zsh     64 pass 5 fail 0 skip 4 s
F opensuse /bin/zsh     [./test/suite:213] test_ts_accepts_options_anywhere
F opensuse /bin/zsh     [./test/suite:223] test_script_accepts_options_anywhere
F opensuse /bin/zsh     [./test/suite:778] test_ts_options
F opensuse /bin/zsh     [./test/suite:816] test_undeclared_variable
F opensuse /bin/zsh     [./test/suite:829] test_ts_allows_exit_trap
# opensuse /bin/ksh     68 pass 1 fail 0 skip 1 s
F opensuse /bin/ksh     [./test/suite:816] test_undeclared_variable
# ubuntu /bin/dash      65 pass 4 fail 0 skip -1 s
F ubuntu /bin/dash      [./test/suite:201] test_ts_runs_cleanly_with_no_tests
F ubuntu /bin/dash      [./test/suite:783] test_include
F ubuntu /bin/dash      [./test/suite:816] test_undeclared_variable
F ubuntu /bin/dash      [./test/suite:862] test_ts_readme_common_tests
# ubuntu /bin/bash      69 pass 0 fail 0 skip 2 s
# ubuntu /bin/zsh       65 pass 4 fail 0 skip 4 s
F ubuntu /bin/zsh       [./test/suite:213] test_ts_accepts_options_anywhere
F ubuntu /bin/zsh       [./test/suite:223] test_script_accepts_options_anywhere
F ubuntu /bin/zsh       [./test/suite:778] test_ts_options
F ubuntu /bin/zsh       [./test/suite:816] test_undeclared_variable
# ubuntu /bin/ksh       68 pass 1 fail 0 skip 1 s
F ubuntu /bin/ksh       [./test/suite:816] test_undeclared_variable

Ubuntu failing tests seem to be the same reported in #22

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.