Repository: evcc-io/evcc
Pull request #16528 (2024-10-06 10:22:06)

Allow marking tests to be skipped
This PR re-enables running template tests on CI.


Patch:
diff --git a/templates/definition/charger/ocpp-abb.yaml b/templates/definition/charger/ocpp-abb.yaml
index 078c94f8..10af39c4 100644
--- a/templates/definition/charger/ocpp-abb.yaml
+++ b/templates/definition/charger/ocpp-abb.yaml
@@ -4,7 +4,7 @@ products:
     description:
       generic: TerraAC
 requirements:
-  evcc: ["sponsorship"]
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
 render: |
diff --git a/templates/definition/charger/ocpp-elvi.yaml b/templates/definition/charger/ocpp-elvi.yaml
index be1c4df6..1ec1990a 100644
--- a/templates/definition/charger/ocpp-elvi.yaml
+++ b/templates/definition/charger/ocpp-elvi.yaml
@@ -4,7 +4,7 @@ products:
     description:
       generic: Elvi
 requirements:
-  evcc: ["sponsorship"]
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
   - name: meter
diff --git a/templates/definition/charger/ocpp-fronius-wattpilot.yaml b/templates/definition/charger/ocpp-fronius-wattpilot.yaml
index 11657c64..03bf03e2 100644
--- a/templates/definition/charger/ocpp-fronius-wattpilot.yaml
+++ b/templates/definition/charger/ocpp-fronius-wattpilot.yaml
@@ -3,6 +3,8 @@ products:
   - brand: Fronius
     description:
       generic: Wattpilot (OCPP)
+requirements:
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
 render: |
diff --git a/templates/definition/charger/ocpp-homecharge.yaml b/templates/definition/charger/ocpp-homecharge.yaml
index 6748c664..561bf9d4 100644
--- a/templates/definition/charger/ocpp-homecharge.yaml
+++ b/templates/definition/charger/ocpp-homecharge.yaml
@@ -13,7 +13,7 @@ requirements:
       The charger must be equipped with a built-in meter (models HC11L/HC22L Energy or Profi).
       For the OCPP configuration, you need to access the EFR-SECC charge controller at http://host/secc.
       For login credentials, ask your dealer or the vendor EFR (www.efr.de).
-  evcc: ["sponsorship"]
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
 render: |
diff --git a/templates/definition/charger/ocpp-orbis-viaris.yaml b/templates/definition/charger/ocpp-orbis-viaris.yaml
index 87cc9dfd..03c473dd 100644
--- a/templates/definition/charger/ocpp-orbis-viaris.yaml
+++ b/templates/definition/charger/ocpp-orbis-viaris.yaml
@@ -4,7 +4,7 @@ products:
     description:
       generic: Viaris
 requirements:
-  evcc: ["sponsorship"]
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
 render: |
diff --git a/templates/definition/charger/ocpp-pulsarplus.yaml b/templates/definition/charger/ocpp-pulsarplus.yaml
index 1d5cda2a..a4061529 100644
--- a/templates/definition/charger/ocpp-pulsarplus.yaml
+++ b/templates/definition/charger/ocpp-pulsarplus.yaml
@@ -19,7 +19,7 @@ requirements:
       * URL: ws://[evcc-adresse]:8887/ (local network connection)
       * Charge Point Identity: Custom value (e.g. serial number of charger) which is reused in configuration as *stationid*
       * Password: leave empty
-  evcc: ["sponsorship"]
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
 render: |
diff --git a/templates/definition/charger/ocpp.yaml b/templates/definition/charger/ocpp.yaml
index a9014681..77d005c4 100644
--- a/templates/definition/charger/ocpp.yaml
+++ b/templates/definition/charger/ocpp.yaml
@@ -47,7 +47,7 @@ requirements:
       * Local network connection
 
       The specific configuration and the actual usable functionality depend on the charger model and its software.
-  evcc: ["sponsorship"]
+  evcc: ["sponsorship", "skiptest"]
 params:
   - preset: ocpp
   - name: autostart
diff --git a/templates/definition/charger/tinkerforge-warp.yaml b/templates/definition/charger/tinkerforge-warp.yaml
index ec9375e6..14591e8b 100644
--- a/templates/definition/charger/tinkerforge-warp.yaml
+++ b/templates/definition/charger/tinkerforge-warp.yaml
@@ -13,6 +13,7 @@ requirements:
   description:
     en: WARP Firmware v2 required. Automatic phase switching requires the additional WARP Energy Manager.
     de: WARP Firmware v2 erforderlich. Für automatische Phasenumschaltung wird zusätzlich der WARP Energy Manager benötigt.
+  evcc: ["skiptest"]
 params:
   - preset: mqtt
   - name: topic
diff --git a/templates/definition/charger/tinkerforge-warp3.yaml b/templates/definition/charger/tinkerforge-warp3.yaml
index 45cc88c8..61df9bc6 100644
--- a/templates/definition/charger/tinkerforge-warp3.yaml
+++ b/templates/definition/charger/tinkerforge-warp3.yaml
@@ -11,6 +11,7 @@ requirements:
   description:
     de: Die automatische Phasenumschaltung bei 1p Fahrzeugen muss deaktiviert sein. Siehe https://docs.warp-charger.com/docs/mqtt_http/api_reference/evse#evse_phase_auto_switch_warp3.
     en: The automatic phase switching for 1p vehicles must be deactivated. Siehe https://docs.warp-charger.com/docs/mqtt_http/api_reference/evse#evse_phase_auto_switch_warp3.
+  evcc: ["skiptest"]
 params:
   - preset: mqtt
   - name: topic
diff --git a/templates/definition/meter/solaranzeige-mqtt.yaml b/templates/definition/meter/solaranzeige-mqtt.yaml
index aed2dfff..3cbc4c44 100644
--- a/templates/definition/meter/solaranzeige-mqtt.yaml
+++ b/templates/definition/meter/solaranzeige-mqtt.yaml
@@ -3,6 +3,8 @@ products:
   - brand: Solaranzeige
     description:
       generic: Solaranzeige
+requirements:
+  evcc: ["skiptest"]
 params:
   - name: usage
     choice: ["grid", "pv"]
diff --git a/templates/definition/meter/tibber-pulse.yaml b/templates/definition/meter/tibber-pulse.yaml
index 8e91b87e..66d55e07 100644
--- a/templates/definition/meter/tibber-pulse.yaml
+++ b/templates/definition/meter/tibber-pulse.yaml
@@ -3,6 +3,8 @@ products:
   - brand: Tibber
     description:
       generic: Pulse
+requirements:
+  evcc: ["skiptest"]
 params:
   - name: usage
     choice: ["grid"]
diff --git a/templates/definition/meter/volkszaehler-ws.yaml b/templates/definition/meter/volkszaehler-ws.yaml
index d284d65a..d9c326b6 100644
--- a/templates/definition/meter/volkszaehler-ws.yaml
+++ b/templates/definition/meter/volkszaehler-ws.yaml
@@ -3,6 +3,8 @@ products:
   - brand: Volkszähler
     description:
       generic: WebSocket API
+requirements:
+  evcc: ["skiptest"]
 group: generic
 params:
   - name: usage
diff --git a/templates/definition/tariff/electricitymaps.yaml b/templates/definition/tariff/electricitymaps.yaml
index a360dfa7..89312b69 100644
--- a/templates/definition/tariff/electricitymaps.yaml
+++ b/templates/definition/tariff/electricitymaps.yaml
@@ -7,6 +7,7 @@ requirements:
   description:
     de: "CO₂-Daten für viele Länder von https://electricitymaps.com/. Der 'Free Personal Tier' beinhaltet leider keine Prognosedaten. Dafür benötigst du einen kommerziellen Account von https://api-portal.electricitymaps.com/. Kostenloser Testmonat verfügbar."
     en: "CO₂ data for many countries from https://electricitymaps.com/. The 'Free Personal Tier' unfortunately does not include forecast data. You'll need a commercial account from https://api-portal.electricitymaps.com/. Free trial available."
+  evcc: ["skiptest"]
 group: co2
 params:
   - name: uri
diff --git a/templates/definition/tariff/groupe-e.yaml b/templates/definition/tariff/groupe-e.yaml
index 542a3f5e..72066562 100644
--- a/templates/definition/tariff/groupe-e.yaml
+++ b/templates/definition/tariff/groupe-e.yaml
@@ -7,6 +7,7 @@ requirements:
   description:
     de: "Nur für die Schweiz verfügbar."
     en: "Only available for Switzerland."
+  evcc: ["skiptest"]
 group: price
 params:
   - preset: tariff-base
diff --git a/templates/definition/tariff/gruenstromindex.yaml b/templates/definition/tariff/gruenstromindex.yaml
index 95c78cf1..85edba5a 100644
--- a/templates/definition/tariff/gruenstromindex.yaml
+++ b/templates/definition/tariff/gruenstromindex.yaml
@@ -5,6 +5,7 @@ requirements:
   description:
     de: "Regionale Emissionsdaten von https://gruenstromindex.de. Nur für Deutschland verfügbar."
     en: "Regional emission data from https://gruenstromindex.de. Only available for Germany."
+  evcc: ["skiptest"]
 group: co2
 params:
   - name: zip
diff --git a/templates/definition/tariff/tibber.yaml b/templates/definition/tariff/tibber.yaml
index e4f1bc89..77dd86de 100644
--- a/templates/definition/tariff/tibber.yaml
+++ b/templates/definition/tariff/tibber.yaml
@@ -5,6 +5,7 @@ requirements:
   description:
     en: "Get your API token from the Tibber developer portal: https://developer.tibber.com/"
     de: "Hol dir deinen API-Token aus dem Tibber-Entwicklerportal: https://developer.tibber.com/"
+  evcc: ["skiptest"]
 group: price
 params:
   - name: token
diff --git a/util/templates/types.go b/util/templates/types.go
index b6e597b4..a2cf2c0e 100644
--- a/util/templates/types.go
+++ b/util/templates/types.go
@@ -56,9 +56,10 @@ const (
 	RequirementEEBUS       = "eebus"       // EEBUS Setup is required
 	RequirementMQTT        = "mqtt"        // MQTT Setup is required
 	RequirementSponsorship = "sponsorship" // Sponsorship is required
+	RequirementSkipTest    = "skiptest"    // Template should be rendered but not tested
 )
 
-var ValidRequirements = []string{RequirementEEBUS, RequirementMQTT, RequirementSponsorship}
+var ValidRequirements = []string{RequirementEEBUS, RequirementMQTT, RequirementSponsorship, RequirementSkipTest}
 
 var predefinedTemplateProperties = []string{
 	"type", "template", "name",


Test patch:
diff --git a/charger/template_test.go b/charger/template_test.go
index d77de331..1576078a 100644
--- a/charger/template_test.go
+++ b/charger/template_test.go
@@ -23,7 +23,8 @@ var acceptable = []string{
 	"loadpoint 1 is not configured", // openWB
 	"recv timeout",
 	"(Client.Timeout exceeded while awaiting headers)",
-	"can only have either uri or device", // modbus
+	"can only have either uri or device",                                   // modbus
+	"connection already registered with different protocol: localhost:502", // modbus
 	"sponsorship required, see https://github.com/evcc-io/evcc#sponsorship",
 	"eebus not configured",
 	"context deadline exceeded",
diff --git a/meter/template_test.go b/meter/template_test.go
index eaf8d134..b933535b 100644
--- a/meter/template_test.go
+++ b/meter/template_test.go
@@ -23,12 +23,13 @@ var acceptable = []string{
 	"i/o timeout",
 	"'sma': missing uri or serial", // SMA
 	"[1ESY1161052714 1ESY1161229249 1EMH0008842285 1ESY1161978584 1EMH0004864048 1ESY1161979033 7ELS8135823805]", // Discovergy
-	"can only have either uri or device",               // modbus
-	"(Client.Timeout exceeded while awaiting headers)", // http
-	"context deadline exceeded",                        // LG ESS
-	"no ping response for 192.0.2.2",                   // SMA
-	"no such network interface",                        // SMA
-	"missing config values: username, password, key",   // E3DC
+	"can only have either uri or device",                                   // modbus
+	"connection already registered with different protocol: localhost:502", // modbus
+	"(Client.Timeout exceeded while awaiting headers)",                     // http
+	"context deadline exceeded",                                            // LG ESS
+	"no ping response for 192.0.2.2",                                       // SMA
+	"no such network interface",                                            // SMA
+	"missing config values: username, password, key",                       // E3DC
 }
 
 func TestTemplates(t *testing.T) {
diff --git a/util/templates/render_testing.go b/util/templates/render_testing.go
index ab6a63b6..e4f28431 100644
--- a/util/templates/render_testing.go
+++ b/util/templates/render_testing.go
@@ -2,7 +2,6 @@ package templates
 
 import (
 	"maps"
-	"os"
 	"slices"
 	"testing"
 
@@ -27,10 +26,12 @@ func test(t *testing.T, tmpl Template, values map[string]interface{}, cb func(va
 		return
 	}
 
-	// actually run the instance if not on CI
-	if os.Getenv("CI") == "" {
-		cb(values)
+	// don't execute if skip test is set
+	if slices.Contains(tmpl.Requirements.EVCC, RequirementSkipTest) {
+		return
 	}
+
+	cb(values)
 }
 
 func TestClass(t *testing.T, class Class, instantiate func(t *testing.T, values map[string]interface{})) {
diff --git a/vehicle/template_test.go b/vehicle/template_test.go
index a9780a1c..c3307fa4 100644
--- a/vehicle/template_test.go
+++ b/vehicle/template_test.go
@@ -22,9 +22,9 @@ var acceptable = []string{
 	"missing credentials",    // Tesla
 	"missing credentials id", // Tronity
 	"missing access and/or refresh token, use `evcc token` to create", // Tesla
-	"login failed: code not found",                                    //Polestar
+	"login failed: code not found",                                    // Polestar
 	"empty instance type- check for missing usage",                    // Merces
-	"invalid vehicle type: tesla",                                     //Tesla
+	"invalid vehicle type: tesla",                                     // Tesla
 }
 
 func TestTemplates(t *testing.T) {