Coder Social home page Coder Social logo

groupon / robo-remote Goto Github PK

View Code? Open in Web Editor NEW
40.0 13.0 29.0 493 KB

RoboRemote is a remote control framework for Robotium. The goal of RoboRemote is to allow for more complex test scenarios by letting the automator write their tests using standard desktop Java/JUnit. All of the Robotium Solo commands are available. RoboRemote also provides some convencience classes to assist in common tasks such as interacting with list views.

License: BSD 3-Clause "New" or "Revised" License

Java 100.00%

robo-remote's Introduction

RoboRemote - A remote control framework for Robotium and UIAutomator

Overview


RoboRemote is a remote control framework for Robotium/UIAutomator. The goal of RoboRemote is to allow for more complex test scenarios by letting the automator write their tests using standard desktop Java/JUnit(other frameworks to be supported in the future). All of the Robotium Solo commands and UIAutomator commands are available. RoboRemote also provides some convencience classes to assist in common tasks such as interacting with list views.

RoboRemote is loosely modeled after Frank for iOS.

Currently Supported Android Versions

  • 2.3+ for Robotium
  • 4.2.2+ for UIAutomator

Specifying Device to Use

If you want to specify a device by serial # for either Robotium or UiAutomator then the ROBO_SERIAL_NUMBER environment variable should be set to the serial number of the device/emulator

Requirements


UiAutomator Remote

UiAutomator remote requires Android API Level 18 to be installed as a maven artifact. It is suggested that the maven android sdk deployer is used for this(https://github.com/mosabua/maven-android-sdk-deployer). Use the tool to install API 18(mvn install -P 4.3) libraries. This will install the android and uiautomator library that is required.

Note: An API Level 17(4.2.2) system can be used to execute tests but calls to UiAutomator functions that require API 18 will fail.

Getting Started - UiAutomator Remote

To use UiAutomator Remote you only need tests with a few setup steps as follows(See examples/HelloWorld/Tests/AutomatorTests.java for an example junit test setup):

  1. Create a test class that extends com.groupon.roboremote.uiautomatorclient.TestBase
  2. Provide the location of the UiAutomatorServer JAR. There are two ways to do this:
    1. Set ROBO_UIAUTOMATOR_JAR as an environment variable to the location of the jar
    2. OR Call setAppEnvironmentVariables("location of jar") in a @BeforeClass
  3. In @Before call super.setUp("test name") and then any commands you need in order to start the app under test4. In @After call tearDown()

To get the JAR file either build it from source(in the UIAutomatorServer directory) or get it from maven(replace 0.6.0-b3 with the latest version #):

mvn org.apache.maven.plugins:maven-dependency-plugin:2.4:get -DrepoUrl=http://oss.sonatype.org/content/repositories/snapshots -Dartifact=com.groupon.roboremote:uiautomatorserver:0.6.0-b3 -Ddest=uiautomatorserver.jar

Maven Depenendencies

Tests

These are the maven dependencies you need to declare in your tests pom:

<dependency>
	<groupId>com.groupon.roboremote</groupId>
    <artifactId>uiautomatorclient</artifactId>
    <version>0.6.0-b3</version>
</dependency>

NOTE: You must add the sonatype snapshots repo to your repositories list. Once 0.5.1 is final this will not be necessary. Add the repository as follows:

<repository>
    <id>oss-sonatype</id>
    <name>oss-sonatype</name>
    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
    <snapshots>
        <enabled>true
    </snapshots>
</repository>

Getting Started - Robotium Remote


You need two things to get started with RoboRemote.

  • A test runner. This is very similar to a Robotium test class except that it extends com.groupon.roboremote.roboremoteserver.RemoteTest instead of ActivityInstrumentationTestCase2. You can actually take the example below and simply change the namespace and target test class. The provided examples(described below) also contain Maven pom files to show how to compile this.

    package com.groupon.roboremote.example.helloworldtestrunner;
    

import com.groupon.roboremote.example.helloworld.HelloWorld; import com.groupon.roboremote.roboremoteserver.*; public class Runner extends RemoteTest { public Runner() throws ClassNotFoundException { super(HelloWorld.class); } public void testRCRunner() throws Exception { startServer(); } }

  • Tests! These are JUnit 4.10 test classes that extend com.groupon.roboremote.roboremoteclient.TestBase. Example tests are provided in the source repository. These can also be compiled with Maven and a sample pom is provided with the example.
    The test executor requires a few environment variables to be set:

    1. ROBO_APP_PACKAGE - This is the package name of the application under test(ex: com.groupon.roboremote.example.HelloWorld)
    2. ROBO_TEST_CLASS - This is the class name that contains the test method we are usng(ex: com.groupon.roboremote.example.helloworldtestrunner.Runner)
    3. ROBO_TEST_RUNNER - The instrumentation test runner to be used(ex: com.groupon.roboremote.example.helloworldtestrunner/com.groupon.roboremote.roboremoteserver.RemoteTestRunner)

    These can be alternatively defined if your tests have a @BeforeClass method that overrides the setUpApp() method from TestBase

    @BeforeClass
      public static void setUpApp() {
          Device.setAppEnvironmentVariables("com.groupon.roboremote.example.helloworld", "com.groupon.roboremote.example.helloworldtestrunner.Runner", "com.groupon.roboremote.example.helloworldtestrunner/com.groupon.roboremote.roboremoteserver.RemoteTestRunner");
      }

Once you have these two items along with your app then you can install the app under test and the test runner to your device and then begin executing tests against an attached device/emulator using desktop JUnit either from maven or the IDE of your choice.

Maven Dependencies

Test Runner

These are the maven dependencies you need to declare in your test runner pom:

<dependency>
    <groupId>com.groupon.roboremote</groupId>
    <artifactId>roboremoteserver</artifactId>
    <version>0.6.0-b3</version>
    <type>apklib</type>
</dependency>

If you are using Gradle an AAR is also provided:

<dependency>
    <groupId>com.groupon.roboremote</groupId>
    <artifactId>roboremoteserveraar</artifactId>
    <version>0.6.0-b3</version>
    <type>aar</type>
</dependency>

Tests

These are the maven dependencies you need to declare in your tests pom:

<dependency>
    <groupId>com.groupon.roboremote</groupId>
    <artifactId>roboremoteclient</artifactId>
    <version>0.6.0-b3</version>
</dependency>
<dependency>
    <groupId>com.groupon.roboremote.roboremoteclient</groupId>
    <artifactId>junit</artifactId>
    <version>0.6.0-b3</version>
</dependency>

Examples


An example project is provided in the examples/HelloWorld directory. The directory structure is as follows:

  • helloworld - This is the application under test which provides a simple list view and an activity to launch based on pressing an itme in the list view
  • helloworldtestrunner - This is the test runner which starts up the RoboRemote HTTP listener and the application under test.
  • Tests -
    • SampleTests - This contains the desktop JUnit based RoboRemote Robotium example tests for the HelloWorld project. Under Tests/src/test is a SampleTests.java which contains a few tests demonstrating various RoboRemote functions.
    • AutomatorTests - This contains the desktop JUnit based RoboRemote UiAutomator example tests for the HelloWorld project. This also serves as an example of how to call various functions in the UiAutomatorClient TestBase to setup the test and run the application you would like to test.
    • CombinedTests - This contains the desktop JUnit based RoboRemote Robotium/UiAutomator combined test example for the HelloWorld project. It demonstrates how UiAutomator and Robotium calls can be mixed.

Compiling the examples

Running "mvn clean install" from the "examples" directory will build the examples. Be sure to run "mvn clean install" from the root first to compile the latest library versions

Installing helloworld/helloworldtestrunner

Execute the following from your repository root:

  1. adb install examples/HelloWorld/helloworld/target/HelloWorld-1.0.apk
  2. adb install examples/HelloWorld/helloworldtestrunner/target/helloworldtestrunner-1.apk

Executing the examples

Execute the following from examples/HelloWorld/Tests

  1. Robotium example: mvn test -Dtest=SampleTests
  2. UiAutomator example:
    1. export ROBO_UIAUTOMATOR_JAR=<path to source root>/UIAutomatorServer/target/uiautomatorserver.jar
    2. mvn test -Dtest=AutomatorTests
  3. Combined example:
    1. export ROBO_UIAUTOMATOR_JAR=<path to source root>/UIAutomatorServer/target/uiautomatorserver.jar
    2. mvn test -Dtest=CombinedTests

Building RoboRemote from Source


In order to build roboremote from source you need to deploy the maven Android modules using the maven-android-sdk-deployer(https://github.com/mosabua/maven-android-sdk-deployer). Install at least versions 4.1, 4.2, 4.3 and 4.4 to get started. After these are installed it is as simple as running "mvn clean install"

Architecture


RoboRemote consists of two main components and several framework specific. The main components are RoboRemoteServerCommon and RoboRemoteClientCommon. Robotium specific components are RoboRemoteServer, RoboRemoteClient and RoboRemoteClientJUnit. The UIAutomator specific components are UIAutomatorServer and UIAutomatorClient. The entire project is managed by Maven and the components are provided as artifacts.

RoboRemoteServerCommon

RoboRemoteServer acts as a HTTP interface to arbitrary function calls. RoboRemoteServer and UIAutomatorServer are specific usages of the component. It accepts requests and provides responses in JSON format. The input JSON describes the class, method and method parameters for the function that is being called.

Example request

Traditional Robotium Syntax:

View tView = solo.getView(android.widget.EditText.class, 0);
RoboRemote map request(POST to http://<device ip>:8080/map):

request={
    "operations": [{
        "query": "solo",
        "operation": {
            "method_name": "getView",
            "arguments": [ "android.widget.EditText", 0 ]
        }
}]}

RoboRemote map response

{
    "results": [
        "android.widget.EditText@470fcf18"
    ],
    "outcome": "SUCCESS"
}

How did that work?

RoboRemote uses Java reflection along with some additional logic to turn the JSON based requests into function calls. All return values from functions are returned as a JSONArray of values. If a function results in a List or an Array then the JSONArray will contain all of the data from the functions return value.

RoboRemoteServerCommon(RemoteServer.java contains a function(getTypeEquivalents) that maps parameter types to equivalent parameter types. This is used to determine if the value that was passed in through JSON(ex: Integer) can be used as an argument to a function that takes a different numerical type. If you are trying to call a function and it is not working properly then a missing mapping in this function is the likely culprit.

What do I do with the String version of the View I requested?

The textual versions of views or class names can be passed back is an argument to a function that requires a class or a view. An example will be shown in the RoboRemoteClient section of this README.

RoboRemoteClientCommon

RoboRemoteClientCommon is a java library(jar) that provides the following functionality:

  • Device/Emulator functions(start app, close app, clear app data)
  • Test logging(using SLF4J and logback)
  • Logcat collection
  • Event based testing(currently logcat monitoring)
  • Failure screenshots

The specific UIAutomator or Robotium implementations provide:

  • Robotium Solo emulation
  • UIAutomator UiObject, UiDevice, UiSelector and UiScrollable emulation
  • Client class to call almost any class/function you want
  • Convenience classes for several components(ex: click an item at an absolute listview item index)

Robotium Solo Emulation

RoboRemoteClient provides com.groupon.roboremote.RoboRemoteClient.Solo which maps all Solo commands that were available as of Robotium 3.1.

Example Robotium Solo request

Traditional Robotium Syntax:

View tView = solo.getView(android.widget.EditText.class, 0);
solo.enterText(tView, "Text to enter");

RoboRemote client request(using com.groupon.roboremote.RoboRemoteClient.Solo):

String tView = Solo.getView("android.widget.EditText", 0);
Solo.enterText(tView, "Text to enter");

UiAutomator Emulation

UIAutomatorClient provides several classes(UiDevice, UiObject, UiSelector, UiScrollable, UiCollection) that provide interfaces to the native classes. UiDevice provides function calls to all of it's functions. The other classes provide call(..) methods to map function calls according to class documentation for UiAutomator.

Example UiAutomator requests Traditional UiAutomator Syntax:

UiObject cancelButton = new UiObject(new UiSelector().text("Cancel").className("android.widget.Button"));
if (cancelButton.exists())
    cancelButton.click();

UiAutomator client request:

UiObject cancelButton = new UiObject(new UiSelector().call("text", "Cancel").call("className", "android.widget.Button"));
if (cancelButton.call("exists").getBoolean(0))
    cancelButton.call("click");

Arbitrary Function Calls

RoboRemoteClientCommon also provides a method(in com.groupon.roboremote.RoboRemoteClient.Client) to call any function in a static/non-static class. The map method is defined as map(String className, String method_name, Object … parameters). If the call is successful then it returns a JSONArray of the results. If the method only has a single return value then it will be in the first element of the JSONArray. Elements in lists/arrays are returned in the same position in the JSONArray as they would be for the normal function call.

Example function call

Traditional method call in a test:

java.lang.System.exit(0);

RoboRemote client request:

Client.map("java.lang.System", "exit", 0)

Note about function calls: You can call methods in static/non-static classes, but cannot call methods in already instantiated classes. In order to use already instantiated classes you will have to add hook methods in your test runner(explained in the Getting Started section of this README). The only exceptions to this are the Robotium Solo class and the test instrumentation. Robotium is pre-instantiated and can be referenced as "solo" in a map call. The test instrumentation can be referenced as "testclass" in a map call.

Complex function calls Robotium 4.x introduced some more complex function calls for web elements. The functions take a By parameter. To support this the system provides a method of storing and retrieving objects. An example is:

Traditional Syntax:

solo.waitForWebElement(By.textContent("myText"))

RoboRemote client request:

new QueryBuilder().map("com.jayway.android.robotium.solo.By", "textContent", "myText").storeResult("byMyText").execute();
Client.map("solo", "waitForWebElement", QueryBuilder.getStoredValue("byMyText"));

Class Instantiation RoboRemoteClientCommon provides a method to do paramaterized class instantion.

Traditional Syntax:

UiObject myObject = new UiObject(mySelector);

RoboRemoteClientCommon Syntax(mySelector is already a stored value in this example):

new QueryBuilder().instantiate("com.android.uiautomator.core.UiObject", QueryBuilder.getStoredValue("mySelector")).execute();
Fields

You may have a neeed to retrieve content from fields in a class. This can be done using the mapField(String className, String) function instead of the map(…) function.

Example field accessor

Traditional field access in Robotium test:

solo.DELETE

RoboRemote client request:

int DELETE = Client.getInstance()mapField("solo", "DELETE").getInt(0)

Access inner class field("android.os.Build.VERSION.SDK_INT"):

int apiLevel = Client.getInstance()mapField("android.os.Build$VERSION", "SDK_INT").getInt(0)

Method Chaining

RoboRemoteClient also allows you to call functions on the return value of a previous function via the com.groupon.roboremote.RoboRemoteClient.QueryBuilder class. You can chain together as many method calls as you would like. The drawback to this class is that you have to map Solo calls instead of using the pre-defined Solo class.

Traditional method call:

float textSize = solo.getText("Sample Text").getTextSize();

RoboRemote QueryBuilder method call:

QueryBuilder query = new QueryBuilder();
query.map("solo", "getText", "Sample Text").call("getTextSize");
JSONArray result = query.execute();
float textSize = new Double(result.getDouble(0)).floatValue();

Traditional method call with a Field:

System.out.println("Foo bar");

RoboRemote QueryBuilder call:

QueryBuilder query = new QueryBuilder();
query.mapField("java.lang.System", "out".call("println", "Foo bar").execute();

Test Hooks

You may find that you want to do more complicated function calls that make more sense to do in Android code rather than through function mapping. Fortunately this is very easy since RoboRemote can call any arbitrary function. The easiest way to do this is to add an additional class(Ex: TestHook) along side your Runner class.

Example testhook class:

package com.groupon.roboremote.example.helloworldtestrunner;
public class TestHook {
    public static void complicatedFunctionCalls() {
        // Do some stuff here
    }
}

Invocation of testhook function:

Client.map("com.groupon.roboremote.example.helloworldtestrunner.TestHook", "complicatedFunctionCalls")

TODO/Limitations


  1. Add compatibility for Android 2.1 - 2.2

Links


Robotium - http://code.google.com/p/robotium/

JUnit - http://www.junit.org/

Frank - https://github.com/moredip/Frank

robo-remote's People

Contributors

dahu2 avatar ddhodapkar avatar dougren avatar qimeijie avatar valampuri 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

Watchers

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

robo-remote's Issues

Problems with execution.....

Hello Robo-remote team, we tried to run this project but we got an error in maven when we try to run the Sample Test class (we already tried to run as mvn line comand). We dont know how to solve this problem. That is the problem:

[INFO] Scanning for projects...
Downloading: http://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloading: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Downloaded: http://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml (11 KB at 4.6 KB/sec)
Downloaded: http://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (21 KB at 6.6 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.677s
[INFO] Finished at: Mon Dec 03 14:31:00 BOT 2012
[INFO] Final Memory: 4M/122M
[INFO] ------------------------------------------------------------------------
[ERROR] No plugin found for prefix 'android' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (C:\Users\lucas.gomes.m2\repository), central (http://repo.maven.apache.org/maven2)] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoPluginFoundForPrefixException

we will wait for a response, and we appreciate the good work of RoboRemote.

Regards,
Lucas Gomes.

test my app with robo-remote

went through all the documentation, trying to test my app with robo-remote(for android 4.0.4),
no success what so ever.
i keep getting this:
INSTRUMENTATION_STATUS: id=ActivityManagerService
INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: ComponentInfo{com.groupon.roboremote.example.helloworldtestrunner/android.test.InstrumentationTestRunner}
INSTRUMENTATION_STATUS_CODE: -1
android.util.AndroidException: INSTRUMENTATION_FAILED: com.groupon.roboremote.example.helloworldtestrunner/android.test.InstrumentationTestRunner
at com.android.commands.am.Am.runInstrument(Am.java:802)
at com.android.commands.am.Am.onRun(Am.java:242)
at com.android.internal.os.BaseCommand.run(BaseCommand.java:47)
at com.android.commands.am.Am.main(Am.java:75)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:235)
at dalvik.system.NativeStart.main(Native Method)

i have modified Runner.java to look like:

package com.groupon.roboremote.example.helloworldtestrunner;
import my.package.name.;
import com.groupon.roboremote.roboremoteserver.
;
public class Runner extends RemoteTest {
public Runner() throws ClassNotFoundException {
super(MyClass.class);
}
public void testRCRunner() throws Exception {
startServer();
}
}

i have exported my project to a jar, installed with mvn:
mvn install:install-file -Dfile=myjar.jar -DgroupId=everything.me -DartifactId=Myjar -Dversion=1.0 -Dpackaging=jar

and then ran mvn clean install from root dir, got failures on uiautomator tests.
ran mvn clean install again from examples, got all the artifacts including the helloworldtestrunner-1.apk

still getting errors.

any advice?

Server does not respond when running the test class

Hi roboremote team,
I'm not able to run the tests in class SampleTests project robo-remote-master/examples/HelloWorld/Tests.
This is the log on Eclipse console.. all tests fals.

[INFO] - c.g.r.roboremoteclient.TestBase:66 setUp - Starting test SampleTests_BVT
[INFO] - c.g.r.roboremoteclient.Device:129 setupLogDirectories - Log directory: B:\Repositorio\IntegracaoContinua\fpf-automatedtest\trunk\Android\SampleProject\robo-remote-master\examples\HelloWorld\Tests\logs\SampleTests_BVT
[INFO] - c.g.r.roboremoteclient.TestBase:105 setUp - Clearing logcat
[INFO] - c.g.r.roboremoteclient.TestBase:108 setUp - Starting logcat
[INFO] - c.g.r.r.logging.EventManager:77 setCheckPoint - Set checkpoint!
[INFO] - c.g.r.roboremoteclient.TestBase:119 setUp - Starting RC Runner
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[INFO] - c.g.r.roboremoteclient.Device:147 startApp - Trying to ping test server..
[WARN] - c.g.r.roboremoteclient.TestBase:50 onFailure - TestBase::OnFailure:: Taking screenshot
[INFO] - c.g.r.roboremoteclient.Device:176 killApp - Trying to see if server is still available..
[INFO] - c.g.r.roboremoteclient.TestBase:133 tearDown - Stopping logcat
[INFO] - c.g.r.roboremoteclient.TestBase:66 setUp - Starting test SampleTests_MethodChaining
....

On debug, I verifies an exception on:
com.groupon.roboremote.roboremoteclient.http.Post.post( ... )

on statement:

    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

exception:
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.io.BufferedInputStream.fill(Unknown Source)
at java.io.BufferedInputStream.read1(Unknown Source)
at java.io.BufferedInputStream.read(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTPHeader(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.http.HttpClient.parseHTTP(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
at com.groupon.roboremote.roboremoteclient.http.Post.post(Post.java:59)
at com.groupon.roboremote.roboremoteclient.Client.post_to_server(Client.java:83)
at com.groupon.roboremote.roboremoteclient.Client.map(Client.java:90)
at com.groupon.roboremote.roboremoteclient.QueryBuilder.execute(QueryBuilder.java:139)
at com.groupon.roboremote.roboremoteclient.Client.map(Client.java:127)
at com.groupon.roboremote.roboremoteclient.LogbackAppender.append(LogbackAppender.java:65)
at com.groupon.roboremote.roboremoteclient.LogbackAppender.append(LogbackAppender.java:1)
at ch.qos.logback.core.AppenderBase.doAppend(AppenderBase.java:85)

you guys know what might be wrong?

thanks for help,

Robson R Ferreira

Problem with integration.

Hi dvanderb, I tried to use your magnifc project to integrate with the framework cucumber to do some BDD tests. So Im facing a little problem, it seems that Im facing a server problem. Because when I execute as Junit it works with no problem and then I run through my features it works too. The problem is when I run with my feature as Junit (without run with Junit first) the console show a message saying Connection Refused. I dont know why this problem is occuring.

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.