Uncategorized – Visionmate – En fullservice digital partner
dagens etp - Marketmate

Marketmate – Sveriges största jämförelsesida av börshandlade produkter

Visionmate utvecklade en plattform för ETP-handel

På rekordtid utvecklade vi en fristående plattform för ETP-handel med direktkoppling mot börsen, vilket möjliggör marknadsinformation i realtid. På Visionmate kan vi med stolthet säga att få teknikbolag inom Fintech klarar av den tidspress som detta tidsschema inneburit.

Nytänkande Fintech

Idén bakom tjänsten kom från en grupp investerare med omfattande branscherfarenhet. Deras motivation kom av trötthet på komplicerade webbplatser och bankernas egna produkter. Deras vision var att erbjuda något nytt och användarvänligt – en plattform som var både nytänkande och enkel att använda.

Med det som utgångspunkt föddes Marketmate – en fristående plattform för ETP-handel.

Nu har konsumenter och aktiva börshandlare möjlighet att smidigt hitta och jämföra de bästa produkterna som passar deras individuella handelsbehov! Lång olja med 3x i hävstång, eller kort OMX med 7x i hävstång? På Marketmate hittas precis allt! Det finns även en hel del inspiration i det redaktionella innehållet. Marknadsinformation som kommer i realtid bidrar till ökad öppenhet och transparens.

warrantlista - Marketmate

På Visionmate ser vi med spänning fram emot de kommande funktionerna som kommer att utvecklas på Marketmate-plattformen!

Alla artiklar

Fördelarna med Java för Applikationsprogrammering

Därför har Java blivit ett populärt val för utvecklare världen över

Java är ett kraftfullt och mångsidigt programmeringsspråk som har varit en ledande kraft inom mjukvaruutveckling i över två decennier. Med dess robusta funktioner och plattformsoberoende natur har Java blivit ett populärt val för utvecklare världen över. På Visionmate är vi stora förespråkare för att använda Java på grund av dess många fördelar. I detta inlägg kommer vi att utforska några av de främsta fördelarna med att använda Java för applikationsprogrammering.

  1. Plattformsoberoende Natur
    En av de mest framstående fördelarna med Java är dess plattformsoberoende natur. Java-program kan köras på vilken plattform som helst som har en Java Virtual Machine (JVM) installerad. Detta gör det möjligt att skriva en enda kodbas som kan användas på olika operativsystem, vilket minskar komplexiteten och resursbehovet för att hantera flera versioner av en applikation.

  2. Enkelhet och Lättanvändlighet
    Java är känt för sin enkelhet och lättanvändlighet. Dess syntax är liknande C++, vilket gör det lätt för utvecklare att lära sig om de redan har erfarenhet av andra C-baserade språk. Java har också ett omfattande ekosystem av verktyg och bibliotek som underlättar utvecklingsprocessen och gör det möjligt att skapa effektiva och pålitliga applikationer.

  3. Stor Gemenskap och Stöd
    Java har en omfattande och engagerad utvecklargemenskap. Det finns gott om resurser, forum och dokumentation tillgängliga för att stödja utvecklare i alla skeden av sina projekt. Denna gemenskapssupport gör det lättare att lösa problem, dela kunskap och hålla sig uppdaterad om de senaste trenderna och bästa praxis inom Java-utveckling.

  4. Robusthet och Tillförlitlighet
    Java är känt för sin robusthet och tillförlitlighet. Språket inkluderar inbyggda mekanismer för felhantering och garanterar minneshantering genom automatisk sophantering. Detta gör Java särskilt lämpat för att utveckla stora och komplexa applikationer där stabilitet och tillförlitlighet är av yttersta vikt.

  5. Objektorienterad Design
    Java är ett objektorienterat programmeringsspråk, vilket innebär att all kod skrivs med hjälp av objekt och klasser. Denna designmetodik främjar återanvändning av kod, ökar flexibiliteten och gör det möjligt att skapa mer modulära och underhållbara applikationer. Objektorienterad design underlättar även samarbete i större utvecklingsteam.

Konkreta fördelar

På Visionmate har vi sett konkreta fördelar med att använda Java i våra projekt. Dess plattformsoberoende natur och kraftfulla egenskaper har gjort det till ett idealiskt verktyg för att skapa robusta och skalbara applikationer. Oavsett om du utvecklar en webbapplikation, mobilapp eller företagsprogramvara, kan Java vara det perfekta verktyget för att möta dina behov.

Alla artiklar

Visionmate sponsor på Elitloppshelgen

Under Elitloppshelgen var vi med som stolt sponsor av K-G Holgersson innovationspris.

Vinnare blev Grumbazz Kini och extra roligt att vår ambassadör Richard fick dela ut priset till en gammal kollega.

Vi jobbar vidare som leverantör av Solvallas webb och kommer släppa deras nya hemsida under 2023.

Alla artiklar

Välkomna Vallagruppens kunder!

Vallagruppen startade för 15 år sedan och är en väletablerad lokal webbyrå i Linköping, efter ett ägarbyte hos dom med ny strategi så välkomnas nu alla kunder till oss på Visionmate. Det här betyder att vi kommer ta över leveransen för hundratals kunder inom områden så som webbutveckling, drift, e-handelslösningar, systemutveckling, sökmotoroptimering mm.

Vi fortsätter att växa på flera olika sätt och i detta fall genom förvärv. Vi öppnar därmed vårt tredje kontor med plats på Stora Torget 3 i Linköping där alla nya som gamla kunder är välkomna. 

Vi är självklart stolta och tacksamma för förtroendet från tidigare ägare på Vallagruppen över att få bära fanan vidare.

Andreas Bagge, VD på Visionmate AB 

Alla artiklar

Amazon kommer till Sverige

Att Amazon kommer till Sverige har nog ingen missat, en jätte som slukad nästan hälften av all e-handel i USA och över en tredjedel i Tyskland. En del skeptiker säger att Amazon tagit andelar till stor del för att dom var tidiga utan riktiga utmanare. Andra skeptiker säger att svenska handlare skyddar sina varumärken och inte kommer vilja ingå i vad dom kallar en ”julgran” av produkter. Kanske blir Amazon inte så framgångsrika i Sverige direkt men på lång sikt blir Amazon definitivt en viktig marknadsplats vare sig bolagen vill eller inte. Men vad behövs då för att lyckas på Amazon? Det kommer behövas kunskap om hur Amazon fungerar och alla rätta tekniska lösningar. På Visionmate har vi noggrant studerat deras API:er och vi kommer börja leverera skarpa tekniska lösningar redan under 2020.

Vi alltid strävar alltid efter ett fullservice erbjudande, antingen i huset eller via partners vi litar på. För att ge våra kunder allra bästa möjligheten att lyckas på Amazon Sverige så har vi nu startat ett samarbete med AMZ. Medan vi står för tekniken kan AMZ ge experthjälp på säljbitarna så som Account Management, Product Ranking, Product Listing, Content Writing, PPC, SEO och Online Sales Analysis.

Wayne Smith från AMZ och vår VD Andreas berättar mer i klippet nedan.

 

 

Vi ses på Amazon! /

Daniel Karlsson, COO

Alla artiklar

Visma.net med Grails

E-handeln växer snabbt och många företag letar efter lösningar som kan automatisera alla processer så som komplexa finansiella transaktioner och avstå från repetitiv redovisning. Det finns en hel del tillgängliga verktyg på marknaden men bland de mer populära hittar vi i Visma.net Financials. Det är en ekonomilösning som har en flexibel konfiguration och fungerar väl för globala organisationer med krav på multinationell rapportering. I det här inlägget tänkte jag beröra dataflödet i det systemet.

Som backend använder jag den senaste versionen av Grails-framework (3.3.5) och för att göra HTTP-requests kommer jag att arbeta med modern Groovy DSL “HttpBuilder-NG”. Du kan hitta mer information om Grails-framework på https://grails.org/.

Först behöver vi inkludera rätt library i vårt projekt för att skapa HTTP- requests. Grails använder Gradle som default builder, så lägg bara till en rad för dependencies i filen build.gradle.

compile "io.github.http-builder-ng:http-builder-ng-core:1.0.3"

Jag vill också nämna credentials. I det här fallet krävs företags-ID och access token.

Sedan behöver vi en tjänst som samlar alla actions för att ta emot och skicka data. Denna tjänst bör vara multifunktionell eftersom vi vill återanvända det med olika API-förfrågningar. För att kontrollera alla tillgängliga API:er, besök https://integration.visma.net/API-index/#.

Det finns en del att välja på men idag kommer vi att arbeta med dessa två: inventering (inventory) och bilaga (attachment). I denna artikel strävar vi bara efter att få data, låt oss som exempel kolla hur man hämtar listan över produkter som ditt företag säljer.

def getFromVisma(String target, def params = [:]) {

   String requestUri = "https://integration.visma.net"

   String requestPath= "/API/controller/api/v1"

   def vismaHeaders = [

           'Accept': "application/json",

           'ipp-company-id': "your company id"

           'ipp-application-type': "Visma.net Financials",

           'Authorization': "your own token"

   ]

   def http = configure {

       request.uri = requestUri

       request.uri.path = requestPath + target

       request.uri.query = params

       request.headers = vismaHeaders

   }

   return http.get {

       response.exception { ex ->

           println ex

       }

   }

}

Controller action för anrop kan se ut såhär:

class AnyController {

    VismaConnectService vismaConnectService

    def getFromVisma() {

        String target = '/inventory'

        def vismaData = vismaConnectService.getFromVisma(target)

        vismaData.each { data ->

            if (data.status == "Active") {
                
                // do something //

            }

        }

    }

}

Vår service method innehåller två parametrar: den första är “target”. När du exempelvis requestar lagerobjekt, ska target vara “inventering”. Den andra är “map” som default är tom. Vanligtvis kan du i parametrarna ange alla de servicefält som Visma erbjuder som exempelvis “lastModifiedDateTime”. Eftersom vi i header angav “application/json” så är resultatet en lista med JSON-objekt och det ser ut så här:

{

        "inventoryId": 00001,

        "inventoryNumber": "00001",

        "status": "Active/Inactive",

        "type": "",

        "description": "",

        "defaultPrice": 0,

        "pendingCost": 0,

        "currentCost": 0,

        "lastCost": 0,

        "lastModifiedDateTime": "2018-01-01T00:00:00.00",

        "attachments": [

            {

                "name": "attachmentName",

                "id": "attachmentId",

                "revision": 1

            }

        ],

        "attributes": [ ],

}

Ovanstående är ett exempel och du kan ha fler eller färre fält. I det här exemplet markerade jag attachmentName och attachmentId. Vi behöver dessa parametrar för att få bifogade filer. Nu tittar vi på koden nedan:

def getAttachment(String attachmentName, String attachmentId) {

   String requestUri = "https://integration.visma.net"

   String requestPath= "/API/controller/api/v1/attachment"

   def vismaHeaders = [

           'ipp-company-id': "your company id",

           'ipp-application-type': "Visma.net Financials",

           'Authorization': "Bearer your own token"

   ]

   def http = configure {

       request.uri = requestUri

       request.uri.path = requestPath + attachmentId

       request.headers = vismaHeaders

   }

   return http.get {

       Download.toFile(delegate, new File("./attachments/${attachmentName}"))

       response.exception { ex ->

           println ex

       }

   }

}

Den sista koden är väldigt lik den första. Största skillnaden är dock att vi kommer att få en File och inte JSON. Men också istället för en File så kan vi få en TempFile eller en Stream. Det beror lite på ditt egna case och requirements.

Slutsats

Eftersom Visma erbjuder mycket större funktionalitet så är exemplen ovan bara toppen på ett isberget. Men du kan absolut använda ovanstående skeleton för att skapa komplexa lösningar för dina olika affärsuppgifter. Likväl, som visat ovan, kan Groovys kraft kombinerat med Grails flexibilitet med sina många plugins hjälpa dig att arbeta med data på ett mycket snabbt och effektivt sätt.

/ Olek, Javautvecklare på Visionmate

Alla artiklar

Funderat på att starta en webbshop? Här kommer 10 saker du bör tänka på

1. Försök att sticka ut. Det finns mycket webbshoppar där ute, så försök att hitta er unika nisch och målgrupp. Genom att fokusera på nischartiklar kan ni hamna högt upp i sökresultat på Google, få omnämningar i sociala medier och på så sätt få upp trafik till sidan. Det är också väldigt viktigt att shoppen har bra SEO-stöd. Att sätta upp en butik utan koppling till omvärlden är lite som att sätta upp en fysisk butik ute i vildmarken och hoppas på bra försäljning…

2. En bild säger mer än tusen ord. Välj ett tydligt bildspråk som ger rätt intryck av artiklarna. För att ge ett bra helhetsintryck är det också viktigt att bilderna har samma ljussättning och bildspråk. Är det kläder som ni ska sälja, då är det även en fördel att inkludera en film på en modell som bär upp plagget. Slutkunden kan enkelt se hur materialet rör sig, hur plagget sitter och du får ett snabbare beslut.

3. Lägg tid på kategorisering. Det är värt att lägga ner initial tankemöda på att hitta en bra kategorisering av dina artiklar och har du mycket artiklar kan du även koppla ihop databasen med en snabb sökmotor. På så sätt hittar din kunder snabbt de artiklar som de gillar. Ingen gillar att leta länge efter vad de söker.

4. Undvik standardmallar. Det finns gott om färdiga e-handelsmallar som ofta inte går att anpassa eller koppla ihop med lager, affär-och leveranssystem. När din webbshop tar fart, då kommer du inse att du saknar funktioner och måste börja om. Det är ofta 80/20 regeln som gäller. De viktigaste 20 % av funktionerna som du vill ha, kommer ta 80 % av tiden att sätta upp. Men för att kunna hantera stora volymer i din försäljning så är det viktigt att varje del i order- och leveranskedjan är automatiserad.

5. När du ska utanför Sverige. Se då till att webbshoppen har stöd för flera språk, valutor och fraktalternativ. Sverige är en förhållandevis liten marknad och säljer dina artiklar bra här, då finns det stora möjligheter att de även säljer bra i andra länder. Det finns också många tredjepartslager att anlita i de länder som du vill leverera till.

6. Undvik tung administration. Koppla ihop din webbshop med ett affärssystem. På så sätt behöver du inte göra dubbeljobb. Webbshoppens försäljning går direkt in i affärssystemet. Plocklistor, orderhantering och fakturering gör du i ditt affärssystem. Med system som exempelvis Visma.net kan du också synkronisera artiklar, priser och kunder från affärssystemet till din webbshop.

7. Även kunderna vill ha koll. Så se till att dina kunder kan se vad som händer med paketet från order till leverans. Med ett välfungerande TA-system integrerat mot webbshoppen kan du och kunden få en bra överblick av leveranserna. Det finns flera olika alternativ att välja på. Ett bra exempel är Unifaun som är väletablerade och täcker de flesta fraktbolagen.

8. Ingen vill vara först. Vi letar alltid efter bekräftelse på att våra val är rätt. Försök att så tidigt som möjligt få in rekommendationer från nöjda kunder. Har du kvalitativa och prisvärda artiklar, då kommer du att tjäna på det. Gör kampanjer och uppmuntra kunderna att skriva rekommendationer. Behandla alltid dina kunder väl. En dålig recension är inte bra så ge alltid kunderna det lilla extra. Du kan även välja att prissätta några utvalda artiklar för att hamna högt på jämförelsesidor. Alla kunder du fått in är din framtida kundgrupp som du sedan kan skicka erbjudanden till i framtiden.

9. Tänk på mobilen. Mer än 50 % av all försäljning sker från mobiler. Se till att din webbshop är optimerad för alla typer webbläsare, läsplattor och mobiler. Samt är certifierad för alla webbläsare.

10. Krångelfri betalning. Gör det enkelt att slutföra ett köp med en lättanvänd check out. Erbjud så många betallösningar som möjligt. Kunder tenderar att handla utifrån deras betalvanor. Till exempel Visa, Mastercard, American Express, PayPal, Klarna, Swish etc. Tänk på att betalningsvanor också skiljer sig mellan olika länder.

Andreas Bagge, VD
Visionmate AB

Alla artiklar

Push-notiser i Grails & React.js baserade webbprojekt

Det här inlägget riktar sig kanske mer mot dig som utvecklare än dig som beställare. Som oftast med system så krävs det en kommunikation mellan servern och klienten. Det är viktigt eftersom olika händelser kan uppstå på servern och en anmälan ska då skickas till klienten. Ett enkelt user cace är en chatt, där användarna kan utbyta meddelanden mellan varandra. Vi kan också använda annan teknik, till exempel Message Queue system. Beroende på behoven så kan man välja den man har mest användning för.

Beskrivning

I det här inlägget kommer vi att diskutera push-meddelanden med hjälp av WebSocket. Jag vill beskriva pedagogiken bakom arbetet, när det kommer till leverans och produktion så har vi självklart enklare rutiner på företaget för att bemöta varje beställning.

Mål

Att kunna genomföra push-notiser i webbapplikationer

Krav

Grails 3.* (Dependencies: Grails Spring WebSocket, Grails Spring Security Rest)

React.js (Dependencies: Sock.js client, Stomp.js)

 

1 – Server konfiguration

Vi måste konfigurera WebSocket message agent för att låta vårt system skicka och ta emot meddelanden via säkra kanaler.

Följande kod (configureClientInboundChannel metod) visar hur man autentiserar via WebSocket. Vi måste vara säkra på att endast en auktoriserad användare kan ansluta, prenumerera och ta emot meddelanden från vår server. Vårt system använder Spring Security Rest och följaktligen är användarna autentiserade via access token i varje förfrågan.

Vi konfigurerar också den endpoint där vår message agent lyssnar på subscription requests och meddelanden (registerStompEndpoints method)

import grails.plugin.springsecurity.rest.token.storage.TokenStorageService
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.messaging.simp.SimpMessageType
import org.springframework.messaging.simp.config.ChannelRegistration
import org.springframework.messaging.simp.stomp.StompHeaderAccessor
import org.springframework.messaging.support.ChannelInterceptorAdapter
import org.springframework.messaging.support.MessageBuilder
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker
import org.springframework.web.socket.config.annotation.StompEndpointRegistry
import org.springframework.messaging.Message
import org.springframework.messaging.MessageChannel
 

@Configuration
@EnableWebSocketMessageBroker
class DefaultWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

   public static final String AUTHORIZATION = 'Authorization'
   public static final String BEARER = 'Bearer'

   @Autowired
   TokenStorageService tokenStorageService
 

@Override
void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
   stompEndpointRegistry.addEndpoint("/ws")
         .setAllowedOrigins("*")
         .withSockJS()
         .setSessionCookieNeeded(false)
}
 

void configureClientInboundChannel(ChannelRegistration registration) {
   registration.setInterceptors(new ChannelInterceptorAdapter() {
      Message<Object> preSend(Message<Object> message,  MessageChannel channel) {
         String token = null
         Boolean access = false
         StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message)
         List tokens = accessor.getNativeHeader(AUTHORIZATION)
         accessor.removeNativeHeader(AUTHORIZATION)

         if(tokens?.size > 0) {
            token = tokens[0]
         }

         if (token?.startsWith(BEARER)) {
            token = token.substring(BEARER.length()).trim()
         }

         switch (accessor.messageType){
            case SimpMessageType.CONNECT: access = (tokenStorageService.loadUserByToken(token))?true:false
               break
            case SimpMessageType.SUBSCRIBE: access = (tokenStorageService.loadUserByToken(token))?true:false
               break
         }
         accessor.setLeaveMutable(true)
         return (access)?MessageBuilder.createMessage(message.payload, accessor.messageHeaders):null
      }
   })
}

2 – Skicka meddelanden

Vi använder Grails Spring WebSocket vilket ger oss den funktionaliteten som behövs för att kunna använda konfigurationen.

I vårt exempel kommer meddelandena att ha en relaterad åtgärd, för att radera, uppdatera eller skapa meddelanden i klienten. Detta är också möjligt om vi skapar olika ämnen för det ändamålet, men i det här fallet är det inte relevant. BrokerService ansvarar för att skicka meddelanden till en destination med hjälp av brokerMesssagingService.

class BrokerService {

    def brokerMessagingTemplate
    /**
     * Send message to destination
     * @param destination
     * @param message
     */
    void send(String destination, Map message) {
        brokerMessagingTemplate.convertAndSend destination, (message as JSON) as String
    }
}

3 – Web client configuration

I webbklienten använder vi Sock.js och Stomp.js för att prenumerera på vår meddelandekanal. För att prenumerera på en kanal i connection request så skickar vi header configuration med användarens token som behörighet.

Vi ställer som en parameter en callback-funktion som kommer att utföras efter att ha mottagit ett meddelande från servern. Med unsubscribe method kan du ta bort en prenumeration, användaren kommer då inte längre att få push-meddelanden när det är gjort.

import {SERVER_URL} from "../config";
import headers from "../security/headers";
import SockJS from 'sockjs-client';
import Stomp from 'stompjs';

/**
 * WebSockets support
 */
const WebSocket = (endpoint) => {

    const socket = SockJS(`${SERVER_URL}/${endpoint}`);
    const client = Stomp.over(socket);

    function subscribe(destination, callback) {
        client.connect(headers(), function(frame) {
            client.subscribe(destination, function(message){
              callback(JSON.parse(message.body))
              }, headers());
           });
        return client;
    }

    function unsubscribe(client){
        for (const sub in client.subscriptions) {
            if (client.subscriptions.hasOwnProperty(sub)) {
                client.unsubscribe(sub);
            }
        }
    }

    return {
        subscribe,
        unsubscribe
    }

};

export default WebSocket;

4 – Prenumeration och mottagande av anmälningar

Vi lägger subscription call på componentDidMount med en klass baserad på React Component.

Vi måste också implementera funktionaliteten som ska utföras när vi får notiserna.

import React from 'react';
import WebSocket from "../../api/WebSocket";
import {ACTION_STATUS} from '../../constant';
import MessageList from "../../components/MessageList";
import { notifyAddedMessage, notifyDeletedMessage,  notifyUpdatedMessage} from "../../actions/actions";


/**
 * Real-time messages
 */
class MessagePanel extends React.Component {

    componentDidMount() {
        this.subscribe();

    }

    componentWillUnmount() {
        if(this.state.client !== undefined)
            WebSocket('ws').unsubscribe(this.state.client);
    }

    subscribe() {
        const callback = (message) => {
            switch (message.action){
                case ACTION_STATUS.DELETED:
                    this.props.notifyDeletedMessage(message.id);
                    break;
                case ACTION_STATUS.UPDATED:
                    this.props.notifyUpdatedMessage(message);
                    break;
                default:
                    this.props.notifyAddedMessage(message);
            }
        };
        callback.bind(this);

        let client;
        if (user instanceof Object) {
            client = WebSocket('ws').subscribe(‘/topic/messages’, callback);
            this.setState({client});
        }
    }

    render() {
        return (
            <MessageList/>
        )
    }
}

Slutsats

Push-meddelanden gör systemet attraktivt och mer användbart, det minskar också serverns latency och förbättrar användarupplevelsen. I många fall kan vi, på ett enkelt sätt och med ett bra resultat, lägga till det med hjälp av WebSockets .

Referens

https://docs.spring.io/spring/docs/5.0.0.BUILD-SNAPSHOT/spring-framework-reference/html/websocket.html

 

/Carlos Senior Developer på Visionmate

Alla artiklar

Introduktion till Kanban och hur det gynnar mindre IT-företag

Visionmate grundades för snart 2 år sedan. Vi har under hela tiden jobbat med att implementera nya verktyg och metoder för att leverera överlägsna tjänster men också för att upprätthålla integriteten inom teamet.

Målet är att alltid förbättras – annars försämras kvaliteten på grund av entropi.

Varför Kanban?

När vi började växa ordentligt under 2018 så behövde vi snabbt hitta lösningar för att hantera arbetsbelastningen på våra projekt. Efter en del research så blev de självklara kandidaterna Scrum och Kanban. Efter att ha undersökt båda metoderna så beslutades att Kanban var mer lämpligt för organisationens krav. Det främst beroende på att vi inte har fasta datum för release och att cyklerna då inte skulle vara lika effektiva. Det kontinuerliga Kanban-flödet var definitivt mer tilltalande.

De strategier som beskrivs här är baserade på “Kanban: Successful Evolutionary Change for Your Technology Business” av David James Anderson – med ändringar som passar vår organisation.

Vårt verktyg för att hålla reda på alla issues (ärenden) är JIRA, och vi använder samma system för våra Kanban-boards. JIRA är vidare länkad till GitHub, så vi enkelt kan spåra alla grenar för att se till att arbetsflödet är korrekt.

Det bör noteras att våra Kanban-implementeringar är ett konstant pågående arbete – vi försöker hela tiden identifiera eventuella problem och förbättra arbetsflödet.

Lägg också till att vi är spridda över 2 länder (lyckligtvis i samma tidszon), vilket nu underlättas av ett lättillgängligt molnbaserat system för alla anställda, det sänker kostnaderna snarare än att öka dem.

Fördelar med Kanban för Visionmate 

  • – Dramatiskt minskad e-post, Skype- och slackkommunikation
  • – Medarbetarna vet vad de ska göra och väljer enkelt sina uppgifter i ett visst projekt
  • – Ledningen har en bättre översikt över pågående projekt och vet vad deras team arbetar med
  • – Kanban-boards används för att visa upp aktuell projektstatus för kunderna
  • – Flaskhalsar identifieras snabbt och kan hanteras
  • – Antalet pågående problem har minskat, ledtiderna reduceras följaktligen också
  • – Eftersom alla problem är kopplade till GitHub-grenar är det mycket lättare att spåra (och återställa, om det behövs) införda ändringar

Genomförande

Vi har delat upp Kanban-board i 2 huvudsakliga sektioner – den första är intern (analys, utveckling och testning) och den andra är extern (UAT). Vi använder Kanban-board för att spåra ärenden som godkänts av kunden och releasar bara ut dem, medan resten får gå tillbaka till utveckling.

På skärmdumpen nedan kan du se kolumnerna som hör till vår Kanban-board.

Backlog

Det första steget är alltid att skapa ett nytt ärende i backlog. Detta kan göras av en utvecklare, projektledare eller en testare. Det är dock bara projektledaren som ska kunna flytta ärenden till input queue, där de plockas upp av en utvecklare för vidare arbete.

Input queue

Utvecklare väljer i allmänhet ärenden utifrån tidigare erfarenheter av det som behöver lösas (om de har arbetat med liknande frågor) eller vad de tycker kommer att gynna kunden mest. Andra kriterier är självklart hur intressant ärendena ser ut att vara :).

Under utveckling

När ett ärende har plockats flyttas det till kolumnen ‘In development’ där kommer det att stanna tills utvecklingen anses vara färdig. Sedan flyttas den till testkolumnen. Vi strävar efter att ha högst cirka 1,5 ärenden per utvecklare i den här kolumnen.

Analys

Om ett problem kräver extern information från projektledare/kund eller kräver ytterligare forskning eller till exempel skjutas på så flyttas den till “Analys” kolumnen. Där kommer den att stanna tills den är klar för utveckling igen. Att ha för många ärenden i kolumnen Analys är en signal till projektledaren att de borde ge mer detaljer till utvecklarna för att driva projektet framåt.

Test-kö

Ärenden från test-kön plockas upp av testteamet. Om utvecklarna är skyldiga att utföra testning är det viktigt att de inte väljer sina egna ärenden och testar – det är alltid bra att få en second opinion på arbetet.

Testning

Vissa ärenden kan kräva mer omfattande testning och kommer därför att ligga kvar i kolumnen ”Testing” tills det är klart.

Testad

Objekt i den testade kolumnen har genomfört intern utveckling och är redo att releasas för ett slutligt godkännande av användaren (UAT).

UAT

Står för User Acceptance Tests. Här mixar vi Kanban-board för utveckling och affärsändamål. Denna kolumn kan visas för våra kunder under projektmöten där vi diskuterar enskilda frågor och får feedback. Godkända ärenden flyttas till färdiga medan avvisade går tillbaka till backlog eller input queue.

Klart

Ärenden i denna kolumn är accepterade av kunden och redo att releasas. Förflyttningen mellan kolumner är begränsad – det är generellt sätt endast tillåtet att flytta ärenden framåt. Ärenden kan komma tillbaka till backlog men endast vid specifika lägen. Det är inte meningen att ärenden ska kunna flyttas fritt på boarden då det skulle skapa en del oreda i flödet.

Slutsats

Introduktionen av Kanban-boards i vårt arbete hade en dramatisk (utan att överdriva) effekt på projektstyrning och effektivitet. Även de mest grundläggande funktionerna hade positiva effekter på arbetsmoralen och bidrog till att förekomma ett kaos.

Om du väljer att implementera Kanban-metoden så är det viktigt att försöka anpassa det så långt det går till era organisatoriska krav.

Dessutom är benchmarking viktigt (särskilt i början). Granska genomförandet i några veckor för att säkerställa att det verkligen fungerar som ni tänkt.

Framtida arbete

Visst finns det några saker som vi planerar att introducera i vårt arbetsflöde inom en snar framtid för att ytterligare förbättra effektiviteten:

  • – expedite items (vi använder dem sällan)
  • – swim lanes
  • – WIP limits (nu har vi bara mjuka limits)

 

/ Radek, Technical Director på Visionmate

Alla artiklar

Tester i React med Jest och Enzyme

Programvarutestning är en väsentlig del av mjukvaruutveckling och säkerställer att koden är hållbar. Automatiska tester hjälper till att hitta nya buggar, förbättra kvaliteten och kompletterar också den manuella testningen.

I den här inlägget kommer vi att gå igenom några av de vanligaste sätten för att testa dina React-applikationer (med CRA ver, 2.1.3).

Då sätter vi igång så låt mig introducera dagens hjältar:

  1. Jest – ett JavaScript-testramverk framtaget av Facebook. Vi använder CRA där Jest installeras automatiskt. Jest’s jobb är att ta alla testfiler i vårt projekt, köra testerna och visa resultatet i terminalen. Jest kan användas med non-React applikationer.
  2. Enzyme – är ett testverktyg utvecklat av Airbnb. Enzyme använder många av de verktyg som tillhandahålls av React för att bygga sitt API. Enzyme fungerar också bara med React.

SET UP

  • React application with CRA
create-react-app testing
cd testing
npm start
  • Enzyme
npm install --save enzyme enzyme-adapter-react-16

Var uppmärksam på vilken versionen av React som du använder. Här använder vi 16, men Enzyme har adapters för alla versioner. Här hittar du fler detaljer: Enzyme installation guide.

För att slutföra konfigurationen måste vi skapa en ny fil som heter setupTests.js i src directory, på så sätt kan vi använda Enzyme i testfilerna. Observera att namnet är viktigt här.

setupTests.js

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({adapter: new Adapter() });

Sådär, installationen är klar!

 

FUNKTIONER I ENZYME

Vi använder funktionerna nedan för att skapa instances av våra komponenter och returnera objekt som vi kan använda för att skriva tester.

  • Static – renders given component och skickar tillbaka ren HTML
  • Shallow – mest grundläggande versionen, renders only given component utan children. Perfekt för unit tests
  • Full DOM – renders the components with all children, här kan vi interagera med komponenterna

TEST STRUCTURE

Testerna kommer att placeras i en ny katalog __tests__

Ha för vana att organisera testerna på det här sättet. Jest kör alla filer som finns inuti.

För att göra det enkelt att identifiera vilket test som tillhör till vilken fil så beskriver vi dem på samma sätt som ”testad fil”: .test.js i slutet.

 

Våra test kommer att vara schemalagda:
it ('test description', function which contain logic of our test);

Funktionen i vårt test ska innehålla få förväntningar, vi kan beskriva det värde som vi förväntar oss att se.

Äntligen TEST!

Nedan är innehållet av två enkla components:

List.js

import React, { Component } from 'react';


class List extends Component {
    render() {
        return (
            <form>
              <h3>Add new element</h3>
              <textarea />
              <div>
                <button>Save</button>
              </div>
            </form>
        );
    }
}

export default List;

App.js

import React from 'react';
import List from './List'

export default()=>{
    return (
        <div><List /></div>
    );
};

Låt oss helt enkelt testa rendering List.js-komponenten. Vi kommer att använda shallow function eftersom vi inte behöver render children. Om komponenten fungerar korrekt kommer testet att fungera, annars misslyckas det.

List.test.js

import React from 'react';
import { shallow } from 'enzyme'; 
import List from '../List';

it('renders without crashing', () => {
  shallow(<List />);
});

Nu kollar vi om testet fungerade genom typing in terminal

npm test

Härligt! Vårt första test lyckades! För att avsluta tryck ctrl+c.

Nu ska vi kontrollera components instance. Vi vill kontrollera om List.js-komponenten finns i App.js.

App.test.js

import React from 'react';
import { shallow } from 'enzyme'; 
import App from '../App';
import List from '../List';

it('shows the list', () => {
  const wrapped = shallow(<App />);
  expect(wrapped.find(List).length).toEqual(1);
});

const wrapped betyder att objektet som vi kommer att ha från shallow (<App />) är en inbäddad version av App-komponenten.

Och båda testerna gick igenom!

På samma sätt som ovan kan vi kontrollera om din komponent innehåller button och input area:

List.test.js

import React from 'react';
import { mount } from 'enzyme'; 
import List from '../List';

it('contains button and text area', () => {
  const wrapped = mount(<List />);
  expect(wrapped.find('textarea').length).toEqual(1);
  expect(wrapped.find('button').length).toEqual(1);
});

Find är ett kraftfull testverktyg. Tack vare det kan vi upptäcka varje klass, HTML-element, attributsyntax, prop eller objektegenskapsväljare och kontrollera om det uppfyller våra förväntningar.

Nu är frågan, hur testar jag ett test?

Vi kan till exempel göra det genom att ändra ett förväntat värde till ett felaktigt. Låt oss låtsas att vi inte har någon button i List.js, vi sätter värde 0 istället för 1 i testfilen. Nu ska testet misslyckas

List.test.js

it('shows button', () => {
    const wrapped = shallow (<List />);
    expect(wrapped.find('button').length).toEqual(0);
});

Japp det misslyckades och Jest visar exakt vad som gick fel.

 

SLUTSATS

Jest och Enzyme är väl integrerade- och flexibla verktyg för att utföra mjukvarutester. Konfigurationen är lätt vilket såklart är en stor fördel. Jag grottade inte ner mig i specifika metoder utan tanken var att ge en god överblick av Jest’s och Enzyms effektivitet.

Origin: www.linkedin.com

Alla artiklar