Giter VIP home page Giter VIP logo

misterjames / genfu Goto Github PK

View Code? Open in Web Editor NEW
826.0 32.0 101.0 14.88 MB

GenFu is a library you can use to generate realistic test data. It is composed of several property fillers that can populate commonly named properties through reflection using an internal database of values or randomly created data. You can override any of the fillers, give GenFu hints on how to fill them.

License: Other

C# 67.47% PowerShell 0.23% HTML 4.70% Less 13.71% SCSS 13.89%

genfu's Introduction

GenFu

http://genfu.io/

Build status NuGet Badge

GenFu is a library you can use to generate realistic test data. It is composed of several property fillers that can populate commonly named properties through reflection using an internal database of values or randomly created data. You can override any of the fillers, give GenFu hints on how to fill them.

GenFu is all about smartly building up objects to use for test and prototype data. It will walk your object graph and fill in the properties on your type with realistic looking data.

Use GenFu's static methods to new up new objects for testing, design-time data or seeding a database.

GenFu runs on AspNetCore50 and can run anywhere core can run.

Installation

GenFu is on NuGet so you can easily add it to your project from the Package Manager Console:

install-package GenFu 

Example Usage

Let's say you have a Person class like so:

    class Person
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Title { get; set; }
        public int Age { get; set; }
        public int NumberOfKids { get; set; }
		
		private string _middleName;
		public void SetMiddleName(string name){ _middleName = name; }
    }

And you want a new instance of Person. With GenFu, you just do this:

    var person = A.New<Person>();

Tada! Your person is now filled with all the data you could ever dream of!

But Wait!

"I don't need no stickin' person! I need a whole list of them!

Easy-peasy lemon squeezy, my friend! Ask for a list instead of a single instance like so:

    var people = A.ListOf<Person>();

There...you have 25 people, this is the default in a list.

"Yeah, sure, fine, but they have to be between the ages of 19 and 25!"

Cool beans, my brother or sister. Here's how GenFu rolls:


    GenFu.Configure<Person>()
        .Fill(p => p.Age)
        .WithinRange(19, 25);
    var people = A.ListOf<Person>();

And you're off to the races! Don't worry, I won't tell your boss how long that took. ;)

Custom Property Fillers

If you want to control how the property is set, you can use your own function (anonymous or otherwise) to do so.

    var blogTitle = "GenFu";

    GenFu.Configure<BlogPost>()
        .Fill(b => b.Title, () => { return blogTitle; })
    
    var post = A.New<BlogPost>();

Method Fillers

If your project uses one-parameter setter methods, you can use GenFu too!

    GenFu.Configure<Person>()
        .MethodFill<string>(x => x.SetMiddleName(null))
    var post = A.New<Person>();

You can use any of the helper methods with setter methods, just like with properties.

Note: Unlike properties, GenFu will not automatically poke data into any methods found. That sounds a little too risky! So if you want GenFu to use your setter methods, specify each method you'd like filled.

More To Come

GenFu was originally created by James Chambers, David Paquette and Simon Timms under the name AngelaSmith.

We are continuing to add more features, such as:

  • Better support for object self-awareness (think of an email address lining up with a first name/last name or username)
  • Additional property fillers

genfu's People

Contributors

aidapsibr avatar ajepst avatar clarkis117 avatar dpaquette avatar dylanblack avatar edblackburn avatar edcharbeneau avatar erikschierboom avatar gpltaylor avatar johnmeilleur avatar lmaslanka avatar marcoregueira avatar misterjames avatar mklaber avatar stimms avatar sulmar avatar xperiandri 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  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  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

genfu's Issues

Static methods not called in filler

Hi!
I've got 2 classes which look like

public partial class QuestionAnswers
{
    public int PK { get; set; }
    public int AnswerNo { get; set; }
    public bool IsCorrect { get; set; }
    public string Text { get; set; }

    public virtual Questions PKNavigation { get; set; }
}

public partial class Questions
{
    public Questions()
    {
        EventQuestionMapping = new HashSet<EventQuestionMapping>();
        QuestionAnswers = new HashSet<QuestionAnswers>();
    }
    public int PK { get; set; }
    public int CategoryId { get; set; }
    public Guid Id { get; set; }
    public string QuestionText { get; set; }
    public string QuestionType { get; set; }

    public virtual ICollection<EventQuestionMapping> EventQuestionMapping { get; set; }
    public virtual ICollection<QuestionAnswers> QuestionAnswers { get; set; }
    public virtual QuestionCodes QuestionCodes { get; set; }
    public virtual QuestionImages QuestionImages { get; set; }
    public virtual Categories Category { get; set; }
}

and a filler that looks like

A.Configure<QuestionAnswers>()
    .Fill(qa => qa.AnswerNo, () => 0)
    .Fill(qa => qa.IsCorrect, () => false);

A.Configure<Questions>()
    .Fill(q => q.CategoryId).WithRandom(context.Categories.Select(i => i.PK))
    .Fill(q => q.Id, Guid.NewGuid) // this Guid.NewGuid never gets called
    .Fill(q=> q.QuestionText, "xxx")
    .Fill(q => q.QuestionType, () => "Text");

Now, when I call

List<Questions> qs = A.ListOf<Questions>().ToList();

Id is Guid.Empty for all Id's.

Asp.Net Core RTM Not working with Nuget 1.1.1

I am working on upgrading my unit test projects from RC2 to RTM and the current version (1.1.1 at the time of writing) does not function. I noticed there has bee a PR completed for 1.1.2 the updates everything to RTM. I have tested it and everything does seem to be working properly. When might you have 1.1.2 available on NuGet?

Improve geospatial generation

Would be cool if the geospatial stuff could generate coordinate points within a bounding box. Other ideas

  • generate LSDs
  • allow for a mode to generate points only within cities or only along roads or only in the countryside or only on dry land

Error Creating List<List<T>>

With the following classes

public enum Category
{
  Food,
  Clothing,
  Toys,
  Recreation
}
public class Product
{
  public int ID { get; set; }
  public string Name { get; set; }
  public Category Category { get; set; }
  public decimal Price { get; set; }
  public decimal Cost { get; set; }
}
public class OrderDetails
{
  public Product Product { get; set; }
  public int Count { get; set; }
  public decimal TotalCost => Product.Price * Count;
}

With a configuration of

A.Configure<Product>()
  .Fill(p => p.Price).WithinRange(1, int.MaxValue)
  .Fill(p => p.Cost).WithinRange(1, int.MaxValue)
  .Fill(p => p.Category).WithRandom(Enum.GetValues(typeof(Category)).OfType<Category>());

  var products = A.ListOf<Product>();

  A.Configure<OrderDetails>()
    .Fill(od => od.Product).WithRandom(products);

   var orderDetails = A.ListOf<List<OrderDetails>>();

The result is:
image

Is there any way around this other than making a manual loop like so?

var orderDetails = new List<List<OrderDetails>>();
for (int i = 0; i < 25; i++)
{
  orderDetails.Add(A.ListOf<OrderDetails>());
}

DateTimeOffset not set?

With the following usage:

A.Configure<ContentChange>()
            .Fill(e => e.Timestamp, () => DateTimeOffset.UtcNow)
            .Fill(e => e.NewContent).WithRandom(contentList)
            .Fill(e => e.PreviousContent).WithRandom(contentList)
            .Fill(e => e.PreviousContentMilliseconds, () => random.Next(60, 1000))
            .Fill(e => e.UnitId).WithRandom(units);
            var changes = A.ListOf<ContentChange>(5000);

where ContentChange is defined like this:

public class ContentChange
    {
        [JsonProperty("previousContentMilliseconds")]
        public double? PreviousContentMilliseconds { get; set; }

        [JsonProperty("newContent")]
        public string NewContent { get; set; }

        [JsonProperty("previousContent")]
        public string PreviousContent { get; set; }

        [JsonProperty("timestamp")]
        public DateTimeOffset Timestamp { get; set; }

        [JsonProperty("unitId")]
        public Guid UnitId { get; set; }
    }

all Timestamp values are set to Zero. Is it a bug or am I using it wrong?

PS: Every other property is filled as expected.

Configuring inherited properties not working

public class BaseThing 
{
   public int Id {get; set;}
}

public class OtherThing  : BaseThing
{
}

Configuring the child class as follows doesn't work:
A.Configure<OtherThing>().Fill(a => a.Id, () => 0)

But this does:
A.Configure<BaseThing>().Fill(a => a.Id, () => 0)

Would be great if both worked properly.

Order of class properties definition affects filler result.

Hello,

The order of the properties in a class affects the filler result:

public class Post {    
  public String Slug { get; set; }
  public String Title { get; set; }
}

[Fact]
public void TitleAndSlugShouldBeEqual() {
  Int32 index = 0;
  A.Configure<Post>() 
   .Fill(x => x.Title, x =>
      new List<String> {
        "A", "B"
      }[index++])
   .Fill(x => x.Slug, x => x.Title);
  List<Post> posts = A.ListOf<Post>(2);
  Assert.Equal(2, posts.Count(x => x.Slug == x.Title));
}

This returns false since the Titles are "A" and "B" but the slugs are null.

If I swap the order of Slug and Title in the class definition than it works fine:

public class Post {    
  public String Title { get; set; }
  public String Slug { get; set; }
}

Any idea why this happens? It took me ages to find this bug ... It is far from obvious.

Thank You,
Miguel

Don't use `A.` prefix

FakeItEasy, a popular mocking library for .NET, already uses the A. prefix. Since both of your projects are great for writing tests, I recommend you change your prefix to something else, so we can GenFu with FakeItEasy without any issues.

Name-based matches for types

Attempt a match on the type name before matching the properties. This would allow for the same property names to be mapped in different domains (i.e. Blog.Title, Employee.Title, Album.Title etc.). Perhaps we have to explore the idea of building a type/property map table in mem for known pairs, with wildcard properties for unmatched types. We can skype it out.


Dave, assigning you since you thought you'd have time to take a stab when we last spoke at the Summit. It would be great to bake this in along with Simon's changes and get a new package up on Nuget. Just assign back to me (or unassign yourself) if you can't tackle it now.

Problem with Resharper parsing GenFu or Visual Studio 2015

I am doing ASP.NET Core RC 2 project with GenFu in Tests project.
Resharper (or Visual Studio) marks following GenFu fill method as error as seen in attached screenshot however solution builds and runs successfully.
I have tried to clean Resharper cache with no success on issue.

Any solution?
genfu

Smarter Property Fillers

Currently, property fillers are all independent of each other. For example, the EmailAddress property filler has no knowledge of the firstname and last name property fillers. It would be great if the Email Address property filler would wait until after the First Name and Last Name have been filled and then user the First Name and Last Name to generate the Email Address.

For example,
Instead of: FirstName = Jane, LastName = Doe, Email = [email protected]
We would get: FirstName = Jane, LastName = Doe, Email = [email protected]

Ability to specify fill using a method instead of a property

Scenario: sometimes, a class will have an explicit setter method for something you might want to set:

SetFirstName(string firstName)
{
_firstName = firstName;
}

I'd like to be able to use AngelaSmith in such a scenario. In this case, I am imagining usage as something like:

Angie.Configure().
MethodFill(b=>b.SetFirstName).AsFirstName().Make();

I am imagining only taking into account single-parameter methods for this for simplicity's sake, at least to start.

What do you think? No promises, but I may try to implement this if this sounds like something that you all would want in the project. I think this would allow AngelaSmith to be usable in a lot more real-world projects.

Method Filler idea

    GenFu.Configure<Person>()
        .MethodFill(x => x.SetMiddleName(GenFu.Fill<string>(), "my default"));

This would you to be explicit about how you fill parameters and would also allow default parameters for same typed parameters.

I haven't installed the tool, I haven't tested it. Just an idea. 😃

Name space and app kernel being named the same causing some pain

Pretty much right there in the title. So for example, when I try to call GenFu.Configure, it doesn't compile because VS thinks I'm making reference to the namespace. If I add using GenFu; to the using directives, it's the same result. At one point, importing other namespaces forced me into actually having to make reference to the GenFu class by typing global::GenFu.GenFu.Configure which was absurd. To fix it, I had to clear my using directives and import everything back in one by one, but still, the best I could come to was GenFu.GenFu.Configure. I'm sure the simple fix would be to rename the main class from GenFu to something else (e.g. GenFu.SomethingElse) to eliminate the ambiguity. This could infact fix the following as well:

also, resharper is ticked about 'A' syntax (i.e. A.ListOf) since it's really accessing a static member of a derived type. It looks like the class is actually empty but deriving from GenFu just for syntactic sugar's sake. I could easily tell resharper to shut it, but I don't want to be modifying my code quality rules just to accomodate the implementation. You may want to consider using composition over inheritance and using A as a static wrapper for GenFu or something along those lines.

System.ArgumentException: Property set method not found.

Hi I am running the following code in Seed method:

            var store = new UserStore<ApplicationUser>(context);
            var manager = new UserManager<ApplicationUser>(store);
            var passwordHash = new PasswordHasher();
            string password = passwordHash.HashPassword("Password@123");

            var users = Angie
                        .Configure<ApplicationUser>()
                        .Fill(user => user.UserName, () => { return Jen.FirstName(); })
                        .Fill(user => user.Email, () => { return Jen.Email(); })
                        .Fill(user => user.PasswordHash, () => { return password; })
                        .Fill(user => user.SecurityStamp, () => { return Guid.NewGuid().ToString(); })
                        .MakeList<ApplicationUser>();

            context.Users.AddOrUpdate(users.ToArray());

And I am getting the following error:

System.ArgumentException: Property set method not found.
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object[] index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object[] index)
at Angela.Core.Angie.SetPropertyValue[T](T instance, PropertyInfo property)
at Angela.Core.Angie.FastFill[T](T instance)
at Angela.Core.Angie.FastMakeT
at Angela.Core.Angie.BuildList[T](Int32 itemCount)
at Angela.Core.Angie.FastListT
at Angela.Core.AngieConfigurator.FastListT
at Angela.Core.AngieConfigurator.MakeListT

Updating to .NET Core RTM and targeting .NET Standard

Hello, I’m creating this issue to start a conversation about updating GenFu to .NET Core 1.0.0 and to target the new .NET Standard system. I’m also working on a pull request that updates the project.json files for this. Although, it still has to be decided which .NET Standard profile to target. I’m partial to targeting .NET Standard 1.6 and .NET Framework 4.5.1 like ASP.NET Core. Please let me know your thoughts, feelings, or concerns.

Working Branch Here: https://github.com/clarkis117/GenFu

Distinct

It would nice to be able to tell GenFu to give me a list with a certain property being distinct for the whole collection.
Something along the following:

class Foo
{
int ID { get; set;}
string Name { get; set; } // Is unique in the datastore
}

A.Configure<Foo>()
    .Fill(f => f.Name)
    .Distinct();

Wrong semantics for member initialization

Given the same objects as in #86 I find it hard to initialize child collections.

For some reason the fillers get applied before the constructor is called. So, if I use the EF7 scaffolding generator, which creates constructors like for "Questions" in the other issue, the child collections will be overwrittem by the constructor after .Fill has been applied.

this makes things like

.Fill(q => q.QuestionAnswers,
    ()=>
    {
        List<QuestionAnswers> answers = A.ListOf<QuestionAnswers>(3); // get me 3 answers
        answers = answers.Select((i, j) =>
        {
            i.AnswerNo = j + 1; // number them properly
            return i;
        }).ToList();
        answers[rng.Next(answers.Count - 1)].IsCorrect = true; // one correct answer
        return answers;
    }
    );

impossible unfortunately.

It would be phantastic if the fillers had the same semantics as member initializers:

new Questions
{
    Id = Guid.NewGuid(),
    QuestionType = "Text",
    QuestionText = "xxx",
    CategoryId = context.Categories.First().PK,
    QuestionAnswers = new List<QuestionAnswers>
    {
        new QuestionAnswers
        {
            AnswerNo = 1,
            IsCorrect = true,
            Text = "A"
        },
        new QuestionAnswers
        {
            AnswerNo = 2,
            IsCorrect = false,
            Text = "B"
        },
        new QuestionAnswers
        {
            AnswerNo = 3,
            IsCorrect = false,
            Text = " C"
        }
    }
}

gives me the properly filled in subcollection because the member initialization is executed after the constructor of "Questions".

Minimum .NET Standard Targets

Following up on this previous issue from #91 and #92

After fiddling around with it a bit, the minimum targets I came up with for GenFu are:
.NET Standard 1.3
.NET Framework 4.5

.NET Standard 1.3 seems to be the lowest version that would allow it to build on .NET Core, with the System.Reflection.TypeExtensions package. Supposedly .NET Standard 1.0 to 1.2 should have feature parity with .NET 4.5; however, when using it large swaths of APIs seem inaccessible. In addition, System.Reflection.TypeExtensions only supports down to .NET Standard 1.3.

Other Notes:
After adding the System.Reflection.TypeExtensions package, I changed several calls to TypeInfo Methods since System.Reflection.TypeExtensions moves them back to the Type Class.

Also considering the recent patch to .NET Core (.NET Core 1.0.1), all .NET Core app model packages should be switched to 1.0.1. This shouldn’t affect platform targeting at all.

CC: @dpaquette @MisterJames
PR: #97

Feature: Set to one of a list of values

Set a property to one of the values from a list. Something like

A.Configure<Apparel>()
      .Fill(apparel => apparel.Type,
      type => OneOf({"Shirt","Trousers","Dress","Blouse","Skirt"});

DefaultValueChecker.HasValue - Use of Magic Strings

Used "Magic Strings" to assert the Object Type. This is not safe if Lamba/Dynamic or Nullable types are uses. It's also an Anti-pattern.

Update: case "int32"
To use something like: (property.GetType() == typeof(string))

Filling two long values appears to cause the second to be filled the same way as the first

For example, if I have two longs like long Id and long BatchId, and Id is something like incrementingId++ and BatchId is .WithRandom(new List { 1, 2, 3, 4, 5 }), BatchId will always be the Id++ and not one of the random values.

However, if i switch Id to an int, suddenly BatchId is within the random range I have defined.

I have some sample code with xunit:

 using Xunit;
 using GenFu;
 using System.Collections.Generic;
 using System;

 namespace MyFirstDnxUnitTests
  {
    public class GenFuTest
    {
    [Fact]
    public void CreateFakeTestData()
    {
        CreateFakeData();
    }

    public void CreateFakeData()
    {
        var ab = new string[]
    {
            "A",
            "B"
    };
        var id = 0;
        GenFu.GenFu.Configure<TestDataType>()
        //this is id++
            .Fill(p => p.Id, () => id++)
       //this is now id++ +1
            .Fill(p => p.BatchId).WithRandom(new List<long> { 1, 2, 3, 4, 5 })
            .Fill(p => p.User).AsFirstName()
            .Fill(p => p.Type).WithinRange(1, 5)
            .Fill(p => p.IsActive).WithRandom(new bool[] { true, false })
            .Fill(p => p.Amount).WithinRange(1, 1000)
            .Fill(p => p.CompleteDate, () => DateTime.MinValue)
            .Fill(p => p.AOrB).WithRandom(ab);

        var testData = A.ListOf<TestDataType>(100);
    }

}

public class TestDataType2
{
    public long Id { get; set; }
    public long BatchId { get; set; }
    public string User { get; set; }
    public string AOrB { get; set; }
    public bool IsActive { get; set; }
    public decimal Amount { get; set; }

    public int Type { get; set; }
    public DateTime CompleteDate { get; set; }
}
}

Filling boolean values

I'm not sure if this exists, it would be nice to specify how to fill boolean values.

Something like:

A
    .Config<Model>()
    .Fill(m => m.IsFeatured, ...)
// Actually, I'm not sure how this would look, but I'd like to specify a percentage
// of the result being true. So "0.3" would fill IsFeatured as true 30% of the time.

Does something like this exist, or at least is this doable?

Corporate Names don't use the same random generator

We are using a deterministic random generator via an overload on the BaseValueGenerator. This allows us to run unit tests that have the same data every time.
However, maybe the Corporate/Name.cs generator should use something like:
return GetRandomValue(names);
Rather than
return names.GetRandomElement();

GetRandomElement uses a private Random generator that cannot be changed.
If the intent is to use GetRandomElement, please allow for setting the Random generator using a fixed seed.

Deep property fill not working

SomeClass.cs

class IdEntity<T> {
public T Id { get; set; }
}

class NamedEntity : IdEntity<int> {
public string Name { get; set; }
}

public class Entity: NamedEntity {
}

Test.cs

using GenFu;
using XUnit;

class EntityFill {
[Fact]
public void EntityFilling() {
A.Configure<Entity>()
.Fill(x => x.Id, () => 0)
.Fill(x => x.Name, () => "Value");

var testData = A.ListOf<Entity>(3);
// Test data not using above configure generating own random values
}
}

Strings are empty in 1.2.0

I think there is an issue with the NuGet package for 1.2.0 where the Resource are not included in the package, this results in an empty string for all string values.

A.New().FirstName //=> ""
A.New().LastName //=> ""
A.New().Age //=> 35

Feature Request: Add own resource-files

It would be nice, if you can register a property-name and the corresponding resource-file (textfile) within the configuration. So it would be open for all types and languages!

Support for .NET Framework 4.0

Could not install package 'AngelaSmith 1.1.0'. You are trying to install this package into a project that targets '.NETFramework,Version=v4.0', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

Set nullables

Angela seems to take issue with nullables. She doesn't set them at all! I'd like to see Angela set a value some of the time. Perhaps in all cases she could set a value and then evil Angela could randomly set the values to nullable as a sort of input fuzzing.

Unique first-/last name over a collection

I need to generate some lists of students for some classes.

Per class the firstname and last name must be unique.

When I do seed my data with: A.ListOf<Student>(30);

I have a problem be cause many duplicates are in there and I do not want to distinct them out...

Thanks!

Guid generation not working

I'm sure I'm missing something obvious, but when I try a very simple test to generate a Guid like this:

var foo = A.New<Guid>();

What I get is this:

00000000-0000-0000-0000-000000000000

I thought maybe it was the most recent version so I rolled back to the last, but alas, same issue.

Install fails on .NET 4.5

Attempting to resolve dependencies for package 'GenFu.1.0.3' with DependencyBehavior 'Lowest'
Install-Package : Unable to resolve dependencies. 'System.Linq 4.0.0' is not compatible with 'GenFu 1.0.3 constraint: System.Linq (≥ 4.0.1-beta-23409)'.
At line:1 char:1

  • Install-Package GenFu
  • - CategoryInfo          : NotSpecified: (:) [Install-Package], Exception
    - FullyQualifiedErrorId : NuGetCmdletUnhandledException,NuGet.PackageManagement.PowerShellCmdlets.InstallPackageCommand
    

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.